/***********************************************************************************************************************
PicoMite MMBasic

audio.c

<COPYRIGHT HOLDERS>  Geoff Graham, Peter Mather
Copyright (c) 2021, <COPYRIGHT HOLDERS> All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 
1.	Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2.	Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
    in the documentation and/or other materials provided with the distribution.
3.	The name MMBasic be used when referring to the interpreter in any documentation and promotional material and the original copyright message be displayed 
    on the console at startup (additional copyright messages may be added).
4.	All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed 
    by the <copyright holder>.
5.	Neither the name of the <copyright holder> nor the names of its contributors may be used to endorse or promote products derived from this software 
    without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDERS> AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDERS> BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

************************************************************************************************************************/
/**
* @file Audio.c
* @author Geoff Graham, Peter Mather
* @brief Source for Audio MMBasic command
*/
/**
 * @cond
 * The following section will be excluded from the documentation.
 */
#include <stdio.h>
#include <stdbool.h>                                // Pascal
#include <stdint.h>                                 // Pascal
#include "ffconf.h"
#include "hardware/pwm.h"
#include "hardware/irq.h"
#include "hardware/flash.h"
#include "MMBasic_Includes.h"
#include "Hardware_Includes.h"
#define DRWAV_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
#define DR_WAV_IMPLEMENTATION
#define DR_WAV_NO_SIMD
#define DR_WAV_NO_STDIO
#include "dr_wav.h"
#define DR_FLAC_IMPLEMENTATION
#define DR_FLAC_NO_STDIO
#define DR_FLAC_NO_CRC
#define DR_FLAC_NO_SIMD
#define DR_FLAC_NO_OGG
#define FLAC_BUFFER_SIZE WAV_BUFFER_SIZE
#define DR_MP3_IMPLEMENTATION
#define DR_MP3_NO_STDIO
//#define DRMP3_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
//#define DRMP3_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
//#define DR_MP3_FLOAT_OUTPUT
#define DR_MP3_ONLY_MP3
#define DR_MP3_NO_SIMD
#define DRMP3_DATA_CHUNK_SIZE 32768
#define MP3_BUFFER_SIZE WAV_BUFFER_SIZE
#ifdef rp2350
#include "dr_mp3.h"
#define MOD_BUFFER_SIZE WAV_BUFFER_SIZE
#else 
#define MOD_BUFFER_SIZE (WAV_BUFFER_SIZE/4)*3
#endif
#include "hardware/pio.h"
#include "hardware/pio_instructions.h"
#include "dr_flac.h"
#include "hxcmod.h"
#include "VS1053.h"
extern BYTE MDD_SDSPI_CardDetectState(void);
#define MAXALBUM 20
extern int InitSDCard(void);
extern const int ErrorMap[21];
extern char *GetCWD(void);
extern void ErrorCheck(int fnbr);
extern const int mapping[101];
extern PIO pioi2s;
extern uint8_t i2ssm;

/********************************************************************************************************************************************
commands and functions
 each function is responsible for decoding a command
 all function names are in the form cmd_xxxx() (for a basic command) or fun_xxxx() (for a basic function) so, if you want to search for the
 function responsible for the NAME command look for cmd_name

 There are 4 items of information that are setup before the command is run.
 All these are globals.

 int cmdtoken	This is the token number of the command (some commands can handle multiple
				statement types and this helps them differentiate)

 char *cmdline	This is the command line terminated with a zero char and trimmed of leading
				spaces.  It may exist anywhere in memory (or even ROM).

 char *nextstmt	This is a pointer to the next statement to be executed.  The only thing a
				command can do with it is save it or change it to some other location.

 char *CurrentLinePtr  This is read only and is set to NULL if the command is in immediate mode.

 The only actions a command can do to change the program flow is to change nextstmt or
 execute longjmp(mark, 1) if it wants to abort the program.

 ********************************************************************************************************************************************/

// define the PWM output frequency for making a tone
const char* const PlayingStr[] = {"PAUSED TONE", "PAUSED FLAC", "PAUSED MP3",  "PAUSED SOUND", "PAUSED MOD", "PAUSED WAV", "OFF", 
    "OFF", "TONE", "SOUND", "WAV", "FLAC", "MP3", 
    "MIDI", "", "MOD", "STREAM","" 
}  ;                              
volatile unsigned char PWM_count = 0;
volatile float PhaseM_left, PhaseM_right;
volatile uint64_t SoundPlay;

volatile e_CurrentlyPlaying CurrentlyPlaying = P_NOTHING;
volatile int v_left, v_right, vol_left = 100, vol_right = 100;
char *wav_buf;                                                      // pointer to the buffer for received wav data
volatile int wav_filesize;                                                   // head and tail of the ring buffer for com1
volatile int tickspersample;
char *WAVInterrupt = NULL;
bool WAVcomplete;
int WAV_fnbr=0;
int PWM_FREQ;
volatile int swingbuf = 0,nextbuf = 0, playreadcomplete = 1;
char *sbuff1=NULL, *sbuff2=NULL;
uint16_t *ubuff1, *ubuff2;
int16_t *g_buff1, *g_buff2;
char *modbuff=NULL;
modcontext *mcontext=NULL;
int modfilesamplerate=22050;
char *pbuffp;
void audio_checks(void);
uint16_t *playbuff;
int16_t *uplaybuff;
volatile int ppos = 0;                                                       // playing position for PLAY WAV
uint8_t nchannels;
volatile uint32_t bcount[3] = {0, 0, 0};
volatile int sound_v_left[MAXSOUNDS]={[0 ... MAXSOUNDS-1 ]=25};
volatile int sound_v_right[MAXSOUNDS]={[0 ... MAXSOUNDS-1 ]=25};
volatile float sound_PhaseAC_left[MAXSOUNDS], sound_PhaseAC_right[MAXSOUNDS];
volatile float sound_PhaseM_left[MAXSOUNDS], sound_PhaseM_right[MAXSOUNDS];
volatile unsigned short * sound_mode_left[MAXSOUNDS];
volatile unsigned short * sound_mode_right[MAXSOUNDS];
volatile uint8_t audiorepeat=1;
volatile uint8_t mono;
//int debug = 0;
drwav *mywav;
drflac *myflac;
a_flist *alist=NULL;
uint8_t trackplaying=0, trackstoplay=0;
unsigned short *noisetable=NULL;
unsigned short *usertable=NULL;
const unsigned short whitenoise[2]={0};
int noloop=0;
int8_t XDCS=-1,XCS=-1,DREQ=-1,XRST=-1;
uint8_t midienabled=0;
int streamsize=0;
volatile int *streamwritepointer=NULL;
volatile int *streamreadpointer=NULL;
char *streambuffer=NULL;
char WAVfilename[FF_MAX_LFN]={0};
#ifdef rp2350
drmp3 *mymp3;
#endif
void* my_malloc(size_t sz, void* pUserData)
{
    return GetMemory(sz);
}
void* my_realloc(void* p, size_t sz, void* pUserData)
{
    return ReAllocMemory((p), (sz));
}
void my_free(void* p, void* pUserData)
{
	FreeMemory((void *)p);
	p=NULL;
}
//*************************************************************************************



volatile float PhaseAC_left, PhaseAC_right;
//#define PSpeedDiv (PeripheralBusSpeed)/2
const unsigned short nulltable[1]={97};
const unsigned short squaretable[1]={99};
const unsigned short triangletable[4096]={
		2000,2001,2003,2005,2007,2009,2011,2012,2014,2016,2018,2020,2022,2024,2025,2027,
		2029,2031,2033,2035,2037,2038,2040,2042,2044,2046,2048,2050,2051,2053,2055,2057,
		2059,2061,2063,2064,2066,2068,2070,2072,2074,2076,2077,2079,2081,2083,2085,2087,
		2089,2090,2092,2094,2096,2098,2100,2102,2103,2105,2107,2109,2111,2113,2115,2116,
		2118,2120,2122,2124,2126,2128,2129,2131,2133,2135,2137,2139,2141,2142,2144,2146,
		2148,2150,2152,2154,2155,2157,2159,2161,2163,2165,2166,2168,2170,2172,2174,2176,
		2178,2179,2181,2183,2185,2187,2189,2191,2192,2194,2196,2198,2200,2202,2204,2205,
		2207,2209,2211,2213,2215,2217,2218,2220,2222,2224,2226,2228,2230,2231,2233,2235,
		2237,2239,2241,2243,2244,2246,2248,2250,2252,2254,2256,2257,2259,2261,2263,2265,
		2267,2269,2270,2272,2274,2276,2278,2280,2282,2283,2285,2287,2289,2291,2293,2295,
		2296,2298,2300,2302,2304,2306,2308,2309,2311,2313,2315,2317,2319,2320,2322,2324,
		2326,2328,2330,2332,2333,2335,2337,2339,2341,2343,2345,2346,2348,2350,2352,2354,
		2356,2358,2359,2361,2363,2365,2367,2369,2371,2372,2374,2376,2378,2380,2382,2384,
		2385,2387,2389,2391,2393,2395,2397,2398,2400,2402,2404,2406,2408,2410,2411,2413,
		2415,2417,2419,2421,2423,2424,2426,2428,2430,2432,2434,2436,2437,2439,2441,2443,
		2445,2447,2449,2450,2452,2454,2456,2458,2460,2462,2463,2465,2467,2469,2471,2473,
		2475,2476,2478,2480,2482,2484,2486,2487,2489,2491,2493,2495,2497,2499,2500,2502,
		2504,2506,2508,2510,2512,2513,2515,2517,2519,2521,2523,2525,2526,2528,2530,2532,
		2534,2536,2538,2539,2541,2543,2545,2547,2549,2551,2552,2554,2556,2558,2560,2562,
		2564,2565,2567,2569,2571,2573,2575,2577,2578,2580,2582,2584,2586,2588,2590,2591,
		2593,2595,2597,2599,2601,2603,2604,2606,2608,2610,2612,2614,2616,2617,2619,2621,
		2623,2625,2627,2629,2630,2632,2634,2636,2638,2640,2641,2643,2645,2647,2649,2651,
		2653,2654,2656,2658,2660,2662,2664,2666,2667,2669,2671,2673,2675,2677,2679,2680,
		2682,2684,2686,2688,2690,2692,2693,2695,2697,2699,2701,2703,2705,2706,2708,2710,
		2712,2714,2716,2718,2719,2721,2723,2725,2727,2729,2731,2732,2734,2736,2738,2740,
		2742,2744,2745,2747,2749,2751,2753,2755,2757,2758,2760,2762,2764,2766,2768,2770,
		2771,2773,2775,2777,2779,2781,2783,2784,2786,2788,2790,2792,2794,2795,2797,2799,
		2801,2803,2805,2807,2808,2810,2812,2814,2816,2818,2820,2821,2823,2825,2827,2829,
		2831,2833,2834,2836,2838,2840,2842,2844,2846,2847,2849,2851,2853,2855,2857,2859,
		2860,2862,2864,2866,2868,2870,2872,2873,2875,2877,2879,2881,2883,2885,2886,2888,
		2890,2892,2894,2896,2898,2899,2901,2903,2905,2907,2909,2911,2912,2914,2916,2918,
		2920,2922,2924,2925,2927,2929,2931,2933,2935,2937,2938,2940,2942,2944,2946,2948,
		2950,2951,2953,2955,2957,2959,2961,2962,2964,2966,2968,2970,2972,2974,2975,2977,
		2979,2981,2983,2985,2987,2988,2990,2992,2994,2996,2998,3000,3001,3003,3005,3007,
		3009,3011,3013,3014,3016,3018,3020,3022,3024,3026,3027,3029,3031,3033,3035,3037,
		3039,3040,3042,3044,3046,3048,3050,3052,3053,3055,3057,3059,3061,3063,3065,3066,
		3068,3070,3072,3074,3076,3078,3079,3081,3083,3085,3087,3089,3091,3092,3094,3096,
		3098,3100,3102,3104,3105,3107,3109,3111,3113,3115,3116,3118,3120,3122,3124,3126,
		3128,3129,3131,3133,3135,3137,3139,3141,3142,3144,3146,3148,3150,3152,3154,3155,
		3157,3159,3161,3163,3165,3167,3168,3170,3172,3174,3176,3178,3180,3181,3183,3185,
		3187,3189,3191,3193,3194,3196,3198,3200,3202,3204,3206,3207,3209,3211,3213,3215,
		3217,3219,3220,3222,3224,3226,3228,3230,3232,3233,3235,3237,3239,3241,3243,3245,
		3246,3248,3250,3252,3254,3256,3258,3259,3261,3263,3265,3267,3269,3270,3272,3274,
		3276,3278,3280,3282,3283,3285,3287,3289,3291,3293,3295,3296,3298,3300,3302,3304,
		3306,3308,3309,3311,3313,3315,3317,3319,3321,3322,3324,3326,3328,3330,3332,3334,
		3335,3337,3339,3341,3343,3345,3347,3348,3350,3352,3354,3356,3358,3360,3361,3363,
		3365,3367,3369,3371,3373,3374,3376,3378,3380,3382,3384,3386,3387,3389,3391,3393,
		3395,3397,3399,3400,3402,3404,3406,3408,3410,3412,3413,3415,3417,3419,3421,3423,
		3425,3426,3428,3430,3432,3434,3436,3437,3439,3441,3443,3445,3447,3449,3450,3452,
		3454,3456,3458,3460,3462,3463,3465,3467,3469,3471,3473,3475,3476,3478,3480,3482,
		3484,3486,3488,3489,3491,3493,3495,3497,3499,3501,3502,3504,3506,3508,3510,3512,
		3514,3515,3517,3519,3521,3523,3525,3527,3528,3530,3532,3534,3536,3538,3540,3541,
		3543,3545,3547,3549,3551,3553,3554,3556,3558,3560,3562,3564,3566,3567,3569,3571,
		3573,3575,3577,3579,3580,3582,3584,3586,3588,3590,3591,3593,3595,3597,3599,3601,
		3603,3604,3606,3608,3610,3612,3614,3616,3617,3619,3621,3623,3625,3627,3629,3630,
		3632,3634,3636,3638,3640,3642,3643,3645,3647,3649,3651,3653,3655,3656,3658,3660,
		3662,3664,3666,3668,3669,3671,3673,3675,3677,3679,3681,3682,3684,3686,3688,3690,
		3692,3694,3695,3697,3699,3701,3703,3705,3707,3708,3710,3712,3714,3716,3718,3720,
		3721,3723,3725,3727,3729,3731,3733,3734,3736,3738,3740,3742,3744,3745,3747,3749,
		3751,3753,3755,3757,3758,3760,3762,3764,3766,3768,3770,3771,3773,3775,3777,3779,
		3781,3783,3784,3786,3788,3790,3792,3794,3796,3797,3799,3801,3803,3805,3807,3809,
		3810,3812,3814,3816,3818,3820,3822,3823,3825,3827,3829,3831,3833,3835,3836,3838,
		3840,3842,3844,3846,3848,3849,3851,3853,3855,3857,3859,3861,3862,3864,3866,3868,
		3870,3872,3874,3875,3877,3879,3881,3883,3885,3887,3888,3890,3892,3894,3896,3898,
		3896,3894,3892,3890,3888,3887,3885,3883,3881,3879,3877,3875,3874,3872,3870,3868,
		3866,3864,3862,3861,3859,3857,3855,3853,3851,3849,3848,3846,3844,3842,3840,3838,
		3836,3835,3833,3831,3829,3827,3825,3823,3822,3820,3818,3816,3814,3812,3810,3809,
		3807,3805,3803,3801,3799,3797,3796,3794,3792,3790,3788,3786,3784,3783,3781,3779,
		3777,3775,3773,3771,3770,3768,3766,3764,3762,3760,3758,3757,3755,3753,3751,3749,
		3747,3745,3744,3742,3740,3738,3736,3734,3733,3731,3729,3727,3725,3723,3721,3720,
		3718,3716,3714,3712,3710,3708,3707,3705,3703,3701,3699,3697,3695,3694,3692,3690,
		3688,3686,3684,3682,3681,3679,3677,3675,3673,3671,3669,3668,3666,3664,3662,3660,
		3658,3656,3655,3653,3651,3649,3647,3645,3643,3642,3640,3638,3636,3634,3632,3630,
		3629,3627,3625,3623,3621,3619,3617,3616,3614,3612,3610,3608,3606,3604,3603,3601,
		3599,3597,3595,3593,3591,3590,3588,3586,3584,3582,3580,3579,3577,3575,3573,3571,
		3569,3567,3566,3564,3562,3560,3558,3556,3554,3553,3551,3549,3547,3545,3543,3541,
		3540,3538,3536,3534,3532,3530,3528,3527,3525,3523,3521,3519,3517,3515,3514,3512,
		3510,3508,3506,3504,3502,3501,3499,3497,3495,3493,3491,3489,3488,3486,3484,3482,
		3480,3478,3476,3475,3473,3471,3469,3467,3465,3463,3462,3460,3458,3456,3454,3452,
		3450,3449,3447,3445,3443,3441,3439,3437,3436,3434,3432,3430,3428,3426,3425,3423,
		3421,3419,3417,3415,3413,3412,3410,3408,3406,3404,3402,3400,3399,3397,3395,3393,
		3391,3389,3387,3386,3384,3382,3380,3378,3376,3374,3373,3371,3369,3367,3365,3363,
		3361,3360,3358,3356,3354,3352,3350,3348,3347,3345,3343,3341,3339,3337,3335,3334,
		3332,3330,3328,3326,3324,3322,3321,3319,3317,3315,3313,3311,3309,3308,3306,3304,
		3302,3300,3298,3296,3295,3293,3291,3289,3287,3285,3283,3282,3280,3278,3276,3274,
		3272,3270,3269,3267,3265,3263,3261,3259,3258,3256,3254,3252,3250,3248,3246,3245,
		3243,3241,3239,3237,3235,3233,3232,3230,3228,3226,3224,3222,3220,3219,3217,3215,
		3213,3211,3209,3207,3206,3204,3202,3200,3198,3196,3194,3193,3191,3189,3187,3185,
		3183,3181,3180,3178,3176,3174,3172,3170,3168,3167,3165,3163,3161,3159,3157,3155,
		3154,3152,3150,3148,3146,3144,3142,3141,3139,3137,3135,3133,3131,3129,3128,3126,
		3124,3122,3120,3118,3116,3115,3113,3111,3109,3107,3105,3104,3102,3100,3098,3096,
		3094,3092,3091,3089,3087,3085,3083,3081,3079,3078,3076,3074,3072,3070,3068,3066,
		3065,3063,3061,3059,3057,3055,3053,3052,3050,3048,3046,3044,3042,3040,3039,3037,
		3035,3033,3031,3029,3027,3026,3024,3022,3020,3018,3016,3014,3013,3011,3009,3007,
		3005,3003,3001,3000,2998,2996,2994,2992,2990,2988,2987,2985,2983,2981,2979,2977,
		2975,2974,2972,2970,2968,2966,2964,2962,2961,2959,2957,2955,2953,2951,2950,2948,
		2946,2944,2942,2940,2938,2937,2935,2933,2931,2929,2927,2925,2924,2922,2920,2918,
		2916,2914,2912,2911,2909,2907,2905,2903,2901,2899,2898,2896,2894,2892,2890,2888,
		2886,2885,2883,2881,2879,2877,2875,2873,2872,2870,2868,2866,2864,2862,2860,2859,
		2857,2855,2853,2851,2849,2847,2846,2844,2842,2840,2838,2836,2834,2833,2831,2829,
		2827,2825,2823,2821,2820,2818,2816,2814,2812,2810,2808,2807,2805,2803,2801,2799,
		2797,2795,2794,2792,2790,2788,2786,2784,2783,2781,2779,2777,2775,2773,2771,2770,
		2768,2766,2764,2762,2760,2758,2757,2755,2753,2751,2749,2747,2745,2744,2742,2740,
		2738,2736,2734,2732,2731,2729,2727,2725,2723,2721,2719,2718,2716,2714,2712,2710,
		2708,2706,2705,2703,2701,2699,2697,2695,2693,2692,2690,2688,2686,2684,2682,2680,
		2679,2677,2675,2673,2671,2669,2667,2666,2664,2662,2660,2658,2656,2654,2653,2651,
		2649,2647,2645,2643,2641,2640,2638,2636,2634,2632,2630,2629,2627,2625,2623,2621,
		2619,2617,2616,2614,2612,2610,2608,2606,2604,2603,2601,2599,2597,2595,2593,2591,
		2590,2588,2586,2584,2582,2580,2578,2577,2575,2573,2571,2569,2567,2565,2564,2562,
		2560,2558,2556,2554,2552,2551,2549,2547,2545,2543,2541,2539,2538,2536,2534,2532,
		2530,2528,2526,2525,2523,2521,2519,2517,2515,2513,2512,2510,2508,2506,2504,2502,
		2500,2499,2497,2495,2493,2491,2489,2487,2486,2484,2482,2480,2478,2476,2475,2473,
		2471,2469,2467,2465,2463,2462,2460,2458,2456,2454,2452,2450,2449,2447,2445,2443,
		2441,2439,2437,2436,2434,2432,2430,2428,2426,2424,2423,2421,2419,2417,2415,2413,
		2411,2410,2408,2406,2404,2402,2400,2398,2397,2395,2393,2391,2389,2387,2385,2384,
		2382,2380,2378,2376,2374,2372,2371,2369,2367,2365,2363,2361,2359,2358,2356,2354,
		2352,2350,2348,2346,2345,2343,2341,2339,2337,2335,2333,2332,2330,2328,2326,2324,
		2322,2320,2319,2317,2315,2313,2311,2309,2308,2306,2304,2302,2300,2298,2296,2295,
		2293,2291,2289,2287,2285,2283,2282,2280,2278,2276,2274,2272,2270,2269,2267,2265,
		2263,2261,2259,2257,2256,2254,2252,2250,2248,2246,2244,2243,2241,2239,2237,2235,
		2233,2231,2230,2228,2226,2224,2222,2220,2218,2217,2215,2213,2211,2209,2207,2205,
		2204,2202,2200,2198,2196,2194,2192,2191,2189,2187,2185,2183,2181,2179,2178,2176,
		2174,2172,2170,2168,2166,2165,2163,2161,2159,2157,2155,2154,2152,2150,2148,2146,
		2144,2142,2141,2139,2137,2135,2133,2131,2129,2128,2126,2124,2122,2120,2118,2116,
		2115,2113,2111,2109,2107,2105,2103,2102,2100,2098,2096,2094,2092,2090,2089,2087,
		2085,2083,2081,2079,2077,2076,2074,2072,2070,2068,2066,2064,2063,2061,2059,2057,
		2055,2053,2051,2050,2048,2046,2044,2042,2040,2038,2037,2035,2033,2031,2029,2027,
		2025,2024,2022,2020,2018,2016,2014,2012,2011,2009,2007,2005,2003,2001,2000,1998,
		1996,1994,1992,1990,1988,1987,1985,1983,1981,1979,1977,1975,1974,1972,1970,1968,
		1966,1964,1962,1961,1959,1957,1955,1953,1951,1949,1948,1946,1944,1942,1940,1938,
		1936,1935,1933,1931,1929,1927,1925,1923,1922,1920,1918,1916,1914,1912,1910,1909,
		1907,1905,1903,1901,1899,1897,1896,1894,1892,1890,1888,1886,1884,1883,1881,1879,
		1877,1875,1873,1871,1870,1868,1866,1864,1862,1860,1858,1857,1855,1853,1851,1849,
		1847,1845,1844,1842,1840,1838,1836,1834,1833,1831,1829,1827,1825,1823,1821,1820,
		1818,1816,1814,1812,1810,1808,1807,1805,1803,1801,1799,1797,1795,1794,1792,1790,
		1788,1786,1784,1782,1781,1779,1777,1775,1773,1771,1769,1768,1766,1764,1762,1760,
		1758,1756,1755,1753,1751,1749,1747,1745,1743,1742,1740,1738,1736,1734,1732,1730,
		1729,1727,1725,1723,1721,1719,1717,1716,1714,1712,1710,1708,1706,1704,1703,1701,
		1699,1697,1695,1693,1691,1690,1688,1686,1684,1682,1680,1679,1677,1675,1673,1671,
		1669,1667,1666,1664,1662,1660,1658,1656,1654,1653,1651,1649,1647,1645,1643,1641,
		1640,1638,1636,1634,1632,1630,1628,1627,1625,1623,1621,1619,1617,1615,1614,1612,
		1610,1608,1606,1604,1602,1601,1599,1597,1595,1593,1591,1589,1588,1586,1584,1582,
		1580,1578,1576,1575,1573,1571,1569,1567,1565,1563,1562,1560,1558,1556,1554,1552,
		1550,1549,1547,1545,1543,1541,1539,1537,1536,1534,1532,1530,1528,1526,1525,1523,
		1521,1519,1517,1515,1513,1512,1510,1508,1506,1504,1502,1500,1499,1497,1495,1493,
		1491,1489,1487,1486,1484,1482,1480,1478,1476,1474,1473,1471,1469,1467,1465,1463,
		1461,1460,1458,1456,1454,1452,1450,1448,1447,1445,1443,1441,1439,1437,1435,1434,
		1432,1430,1428,1426,1424,1422,1421,1419,1417,1415,1413,1411,1409,1408,1406,1404,
		1402,1400,1398,1396,1395,1393,1391,1389,1387,1385,1383,1382,1380,1378,1376,1374,
		1372,1370,1369,1367,1365,1363,1361,1359,1358,1356,1354,1352,1350,1348,1346,1345,
		1343,1341,1339,1337,1335,1333,1332,1330,1328,1326,1324,1322,1320,1319,1317,1315,
		1313,1311,1309,1307,1306,1304,1302,1300,1298,1296,1294,1293,1291,1289,1287,1285,
		1283,1281,1280,1278,1276,1274,1272,1270,1268,1267,1265,1263,1261,1259,1257,1255,
		1254,1252,1250,1248,1246,1244,1242,1241,1239,1237,1235,1233,1231,1229,1228,1226,
		1224,1222,1220,1218,1216,1215,1213,1211,1209,1207,1205,1204,1202,1200,1198,1196,
		1194,1192,1191,1189,1187,1185,1183,1181,1179,1178,1176,1174,1172,1170,1168,1166,
		1165,1163,1161,1159,1157,1155,1153,1152,1150,1148,1146,1144,1142,1140,1139,1137,
		1135,1133,1131,1129,1127,1126,1124,1122,1120,1118,1116,1114,1113,1111,1109,1107,
		1105,1103,1101,1100,1098,1096,1094,1092,1090,1088,1087,1085,1083,1081,1079,1077,
		1075,1074,1072,1070,1068,1066,1064,1062,1061,1059,1057,1055,1053,1051,1050,1048,
		1046,1044,1042,1040,1038,1037,1035,1033,1031,1029,1027,1025,1024,1022,1020,1018,
		1016,1014,1012,1011,1009,1007,1005,1003,1001,999,998,996,994,992,990,988,
		986,985,983,981,979,977,975,973,972,970,968,966,964,962,960,959,
		957,955,953,951,949,947,946,944,942,940,938,936,934,933,931,929,
		927,925,923,921,920,918,916,914,912,910,908,907,905,903,901,899,
		897,895,894,892,890,888,886,884,883,881,879,877,875,873,871,870,
		868,866,864,862,860,858,857,855,853,851,849,847,845,844,842,840,
		838,836,834,832,831,829,827,825,823,821,819,818,816,814,812,810,
		808,806,805,803,801,799,797,795,793,792,790,788,786,784,782,780,
		779,777,775,773,771,769,767,766,764,762,760,758,756,754,753,751,
		749,747,745,743,741,740,738,736,734,732,730,729,727,725,723,721,
		719,717,716,714,712,710,708,706,704,703,701,699,697,695,693,691,
		690,688,686,684,682,680,678,677,675,673,671,669,667,665,664,662,
		660,658,656,654,652,651,649,647,645,643,641,639,638,636,634,632,
		630,628,626,625,623,621,619,617,615,613,612,610,608,606,604,602,
		600,599,597,595,593,591,589,587,586,584,582,580,578,576,575,573,
		571,569,567,565,563,562,560,558,556,554,552,550,549,547,545,543,
		541,539,537,536,534,532,530,528,526,524,523,521,519,517,515,513,
		511,510,508,506,504,502,500,498,497,495,493,491,489,487,485,484,
		482,480,478,476,474,472,471,469,467,465,463,461,459,458,456,454,
		452,450,448,446,445,443,441,439,437,435,433,432,430,428,426,424,
		422,420,419,417,415,413,411,409,408,406,404,402,400,398,396,395,
		393,391,389,387,385,383,382,380,378,376,374,372,370,369,367,365,
		363,361,359,357,356,354,352,350,348,346,344,343,341,339,337,335,
		333,331,330,328,326,324,322,320,318,317,315,313,311,309,307,305,
		304,302,300,298,296,294,292,291,289,287,285,283,281,279,278,276,
		274,272,270,268,266,265,263,261,259,257,255,254,252,250,248,246,
		244,242,241,239,237,235,233,231,229,228,226,224,222,220,218,216,
		215,213,211,209,207,205,203,202,200,198,196,194,192,190,189,187,
		185,183,181,179,177,176,174,172,170,168,166,164,163,161,159,157,
		155,153,151,150,148,146,144,142,140,138,137,135,133,131,129,127,
		125,124,122,120,118,116,114,112,111,109,107,105,103,101,100,98,
		100,101,103,105,107,109,111,112,114,116,118,120,122,124,125,127,
		129,131,133,135,137,138,140,142,144,146,148,150,151,153,155,157,
		159,161,163,164,166,168,170,172,174,176,177,179,181,183,185,187,
		189,190,192,194,196,198,200,202,203,205,207,209,211,213,215,216,
		218,220,222,224,226,228,229,231,233,235,237,239,241,242,244,246,
		248,250,252,254,255,257,259,261,263,265,266,268,270,272,274,276,
		278,279,281,283,285,287,289,291,292,294,296,298,300,302,304,305,
		307,309,311,313,315,317,318,320,322,324,326,328,330,331,333,335,
		337,339,341,343,344,346,348,350,352,354,356,357,359,361,363,365,
		367,369,370,372,374,376,378,380,382,383,385,387,389,391,393,395,
		396,398,400,402,404,406,408,409,411,413,415,417,419,420,422,424,
		426,428,430,432,433,435,437,439,441,443,445,446,448,450,452,454,
		456,458,459,461,463,465,467,469,471,472,474,476,478,480,482,484,
		485,487,489,491,493,495,497,498,500,502,504,506,508,510,511,513,
		515,517,519,521,523,524,526,528,530,532,534,536,537,539,541,543,
		545,547,549,550,552,554,556,558,560,562,563,565,567,569,571,573,
		575,576,578,580,582,584,586,587,589,591,593,595,597,599,600,602,
		604,606,608,610,612,613,615,617,619,621,623,625,626,628,630,632,
		634,636,638,639,641,643,645,647,649,651,652,654,656,658,660,662,
		664,665,667,669,671,673,675,677,678,680,682,684,686,688,690,691,
		693,695,697,699,701,703,704,706,708,710,712,714,716,717,719,721,
		723,725,727,729,730,732,734,736,738,740,741,743,745,747,749,751,
		753,754,756,758,760,762,764,766,767,769,771,773,775,777,779,780,
		782,784,786,788,790,792,793,795,797,799,801,803,805,806,808,810,
		812,814,816,818,819,821,823,825,827,829,831,832,834,836,838,840,
		842,844,845,847,849,851,853,855,857,858,860,862,864,866,868,870,
		871,873,875,877,879,881,883,884,886,888,890,892,894,895,897,899,
		901,903,905,907,908,910,912,914,916,918,920,921,923,925,927,929,
		931,933,934,936,938,940,942,944,946,947,949,951,953,955,957,959,
		960,962,964,966,968,970,972,973,975,977,979,981,983,985,986,988,
		990,992,994,996,998,999,1001,1003,1005,1007,1009,1011,1012,1014,1016,1018,
		1020,1022,1024,1025,1027,1029,1031,1033,1035,1037,1038,1040,1042,1044,1046,1048,
		1050,1051,1053,1055,1057,1059,1061,1062,1064,1066,1068,1070,1072,1074,1075,1077,
		1079,1081,1083,1085,1087,1088,1090,1092,1094,1096,1098,1100,1101,1103,1105,1107,
		1109,1111,1113,1114,1116,1118,1120,1122,1124,1126,1127,1129,1131,1133,1135,1137,
		1139,1140,1142,1144,1146,1148,1150,1152,1153,1155,1157,1159,1161,1163,1165,1166,
		1168,1170,1172,1174,1176,1178,1179,1181,1183,1185,1187,1189,1191,1192,1194,1196,
		1198,1200,1202,1204,1205,1207,1209,1211,1213,1215,1216,1218,1220,1222,1224,1226,
		1228,1229,1231,1233,1235,1237,1239,1241,1242,1244,1246,1248,1250,1252,1254,1255,
		1257,1259,1261,1263,1265,1267,1268,1270,1272,1274,1276,1278,1280,1281,1283,1285,
		1287,1289,1291,1293,1294,1296,1298,1300,1302,1304,1306,1307,1309,1311,1313,1315,
		1317,1319,1320,1322,1324,1326,1328,1330,1332,1333,1335,1337,1339,1341,1343,1345,
		1346,1348,1350,1352,1354,1356,1358,1359,1361,1363,1365,1367,1369,1370,1372,1374,
		1376,1378,1380,1382,1383,1385,1387,1389,1391,1393,1395,1396,1398,1400,1402,1404,
		1406,1408,1409,1411,1413,1415,1417,1419,1421,1422,1424,1426,1428,1430,1432,1434,
		1435,1437,1439,1441,1443,1445,1447,1448,1450,1452,1454,1456,1458,1460,1461,1463,
		1465,1467,1469,1471,1473,1474,1476,1478,1480,1482,1484,1486,1487,1489,1491,1493,
		1495,1497,1499,1500,1502,1504,1506,1508,1510,1512,1513,1515,1517,1519,1521,1523,
		1525,1526,1528,1530,1532,1534,1536,1537,1539,1541,1543,1545,1547,1549,1550,1552,
		1554,1556,1558,1560,1562,1563,1565,1567,1569,1571,1573,1575,1576,1578,1580,1582,
		1584,1586,1588,1589,1591,1593,1595,1597,1599,1601,1602,1604,1606,1608,1610,1612,
		1614,1615,1617,1619,1621,1623,1625,1627,1628,1630,1632,1634,1636,1638,1640,1641,
		1643,1645,1647,1649,1651,1653,1654,1656,1658,1660,1662,1664,1666,1667,1669,1671,
		1673,1675,1677,1679,1680,1682,1684,1686,1688,1690,1691,1693,1695,1697,1699,1701,
		1703,1704,1706,1708,1710,1712,1714,1716,1717,1719,1721,1723,1725,1727,1729,1730,
		1732,1734,1736,1738,1740,1742,1743,1745,1747,1749,1751,1753,1755,1756,1758,1760,
		1762,1764,1766,1768,1769,1771,1773,1775,1777,1779,1781,1782,1784,1786,1788,1790,
		1792,1794,1795,1797,1799,1801,1803,1805,1807,1808,1810,1812,1814,1816,1818,1820,
		1821,1823,1825,1827,1829,1831,1833,1834,1836,1838,1840,1842,1844,1845,1847,1849,
		1851,1853,1855,1857,1858,1860,1862,1864,1866,1868,1870,1871,1873,1875,1877,1879,
		1881,1883,1884,1886,1888,1890,1892,1894,1896,1897,1899,1901,1903,1905,1907,1909,
		1910,1912,1914,1916,1918,1920,1922,1923,1925,1927,1929,1931,1933,1935,1936,1938,
		1940,1942,1944,1946,1948,1949,1951,1953,1955,1957,1959,1961,1962,1964,1966,1968,
		1970,1972,1974,1975,1977,1979,1981,1983,1985,1987,1988,1990,1992,1994,1996,1998
};
const unsigned short sawtable[1]={98};
const unsigned short SineTable[4096] = {
		2000,2003,2006,2009,2012,2015,2017,2020,2023,2026,2029,2032,2035,2038,2041,2044,2047,2050,2052,2055,2058,2061,2064,2067,2070,2073,2076,2079,2082,2084,2087,2090,
		2093,2096,2099,2102,2105,2108,2111,2114,2117,2119,2122,2125,2128,2131,2134,2137,2140,2143,2146,2148,2151,2154,2157,2160,2163,2166,2169,2172,2175,2178,2180,2183,
		2186,2189,2192,2195,2198,2201,2204,2207,2209,2212,2215,2218,2221,2224,2227,2230,2233,2235,2238,2241,2244,2247,2250,2253,2256,2259,2261,2264,2267,2270,2273,2276,
		2279,2282,2285,2287,2290,2293,2296,2299,2302,2305,2308,2310,2313,2316,2319,2322,2325,2328,2331,2333,2336,2339,2342,2345,2348,2351,2354,2356,2359,2362,2365,2368,
		2371,2374,2376,2379,2382,2385,2388,2391,2394,2396,2399,2402,2405,2408,2411,2413,2416,2419,2422,2425,2428,2430,2433,2436,2439,2442,2445,2448,2450,2453,2456,2459,
		2462,2464,2467,2470,2473,2476,2479,2481,2484,2487,2490,2493,2496,2498,2501,2504,2507,2510,2512,2515,2518,2521,2524,2526,2529,2532,2535,2538,2540,2543,2546,2549,
		2552,2554,2557,2560,2563,2565,2568,2571,2574,2577,2579,2582,2585,2588,2590,2593,2596,2599,2602,2604,2607,2610,2613,2615,2618,2621,2624,2626,2629,2632,2635,2637,
		2640,2643,2646,2648,2651,2654,2657,2659,2662,2665,2667,2670,2673,2676,2678,2681,2684,2687,2689,2692,2695,2697,2700,2703,2706,2708,2711,2714,2716,2719,2722,2724,
		2727,2730,2732,2735,2738,2741,2743,2746,2749,2751,2754,2757,2759,2762,2765,2767,2770,2773,2775,2778,2781,2783,2786,2789,2791,2794,2797,2799,2802,2804,2807,2810,
		2812,2815,2818,2820,2823,2826,2828,2831,2833,2836,2839,2841,2844,2846,2849,2852,2854,2857,2859,2862,2865,2867,2870,2872,2875,2878,2880,2883,2885,2888,2891,2893,
		2896,2898,2901,2903,2906,2908,2911,2914,2916,2919,2921,2924,2926,2929,2931,2934,2937,2939,2942,2944,2947,2949,2952,2954,2957,2959,2962,2964,2967,2969,2972,2974,
		2977,2979,2982,2984,2987,2989,2992,2994,2997,2999,3002,3004,3007,3009,3012,3014,3016,3019,3021,3024,3026,3029,3031,3034,3036,3039,3041,3043,3046,3048,3051,3053,
		3056,3058,3060,3063,3065,3068,3070,3072,3075,3077,3080,3082,3084,3087,3089,3092,3094,3096,3099,3101,3104,3106,3108,3111,3113,3115,3118,3120,3122,3125,3127,3129,
		3132,3134,3137,3139,3141,3144,3146,3148,3150,3153,3155,3157,3160,3162,3164,3167,3169,3171,3174,3176,3178,3180,3183,3185,3187,3190,3192,3194,3196,3199,3201,3203,
		3205,3208,3210,3212,3214,3217,3219,3221,3223,3226,3228,3230,3232,3234,3237,3239,3241,3243,3245,3248,3250,3252,3254,3256,3259,3261,3263,3265,3267,3269,3272,3274,
		3276,3278,3280,3282,3285,3287,3289,3291,3293,3295,3297,3300,3302,3304,3306,3308,3310,3312,3314,3316,3319,3321,3323,3325,3327,3329,3331,3333,3335,3337,3339,3341,
		3344,3346,3348,3350,3352,3354,3356,3358,3360,3362,3364,3366,3368,3370,3372,3374,3376,3378,3380,3382,3384,3386,3388,3390,3392,3394,3396,3398,3400,3402,3404,3406,
		3408,3410,3412,3414,3416,3418,3419,3421,3423,3425,3427,3429,3431,3433,3435,3437,3439,3441,3442,3444,3446,3448,3450,3452,3454,3456,3458,3459,3461,3463,3465,3467,
		3469,3471,3472,3474,3476,3478,3480,3482,3483,3485,3487,3489,3491,3492,3494,3496,3498,3500,3501,3503,3505,3507,3509,3510,3512,3514,3516,3517,3519,3521,3523,3524,
		3526,3528,3530,3531,3533,3535,3536,3538,3540,3542,3543,3545,3547,3548,3550,3552,3553,3555,3557,3558,3560,3562,3563,3565,3567,3568,3570,3572,3573,3575,3577,3578,
		3580,3581,3583,3585,3586,3588,3589,3591,3593,3594,3596,3597,3599,3601,3602,3604,3605,3607,3608,3610,3611,3613,3615,3616,3618,3619,3621,3622,3624,3625,3627,3628,
		3630,3631,3633,3634,3636,3637,3639,3640,3642,3643,3644,3646,3647,3649,3650,3652,3653,3655,3656,3657,3659,3660,3662,3663,3665,3666,3667,3669,3670,3672,3673,3674,
		3676,3677,3678,3680,3681,3682,3684,3685,3687,3688,3689,3691,3692,3693,3694,3696,3697,3698,3700,3701,3702,3704,3705,3706,3707,3709,3710,3711,3713,3714,3715,3716,
		3718,3719,3720,3721,3723,3724,3725,3726,3727,3729,3730,3731,3732,3733,3735,3736,3737,3738,3739,3741,3742,3743,3744,3745,3746,3747,3749,3750,3751,3752,3753,3754,
		3755,3756,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,
		3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3810,3811,3812,3813,3814,3815,3816,3816,3817,
		3818,3819,3820,3821,3822,3822,3823,3824,3825,3826,3826,3827,3828,3829,3830,3830,3831,3832,3833,3833,3834,3835,3836,3837,3837,3838,3839,3839,3840,3841,3842,3842,
		3843,3844,3844,3845,3846,3847,3847,3848,3849,3849,3850,3851,3851,3852,3853,3853,3854,3854,3855,3856,3856,3857,3858,3858,3859,3859,3860,3861,3861,3862,3862,3863,
		3863,3864,3865,3865,3866,3866,3867,3867,3868,3868,3869,3869,3870,3871,3871,3872,3872,3873,3873,3874,3874,3874,3875,3875,3876,3876,3877,3877,3878,3878,3879,3879,
		3879,3880,3880,3881,3881,3882,3882,3882,3883,3883,3883,3884,3884,3885,3885,3885,3886,3886,3886,3887,3887,3887,3888,3888,3888,3889,3889,3889,3890,3890,3890,3891,
		3891,3891,3891,3892,3892,3892,3892,3893,3893,3893,3893,3894,3894,3894,3894,3895,3895,3895,3895,3895,3896,3896,3896,3896,3896,3897,3897,3897,3897,3897,3897,3898,
		3898,3898,3898,3898,3898,3898,3898,3899,3899,3899,3899,3899,3899,3899,3899,3899,3899,3899,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,
		3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3900,3899,3899,3899,3899,3899,3899,3899,3899,3899,3899,3899,3898,3898,3898,3898,3898,3898,
		3898,3898,3897,3897,3897,3897,3897,3897,3896,3896,3896,3896,3896,3895,3895,3895,3895,3895,3894,3894,3894,3894,3893,3893,3893,3893,3892,3892,3892,3892,3891,3891,
		3891,3891,3890,3890,3890,3889,3889,3889,3888,3888,3888,3887,3887,3887,3886,3886,3886,3885,3885,3885,3884,3884,3883,3883,3883,3882,3882,3882,3881,3881,3880,3880,
		3879,3879,3879,3878,3878,3877,3877,3876,3876,3875,3875,3874,3874,3874,3873,3873,3872,3872,3871,3871,3870,3869,3869,3868,3868,3867,3867,3866,3866,3865,3865,3864,
		3863,3863,3862,3862,3861,3861,3860,3859,3859,3858,3858,3857,3856,3856,3855,3854,3854,3853,3853,3852,3851,3851,3850,3849,3849,3848,3847,3847,3846,3845,3844,3844,
		3843,3842,3842,3841,3840,3839,3839,3838,3837,3837,3836,3835,3834,3833,3833,3832,3831,3830,3830,3829,3828,3827,3826,3826,3825,3824,3823,3822,3822,3821,3820,3819,
		3818,3817,3816,3816,3815,3814,3813,3812,3811,3810,3810,3809,3808,3807,3806,3805,3804,3803,3802,3801,3800,3799,3799,3798,3797,3796,3795,3794,3793,3792,3791,3790,
		3789,3788,3787,3786,3785,3784,3783,3782,3781,3780,3779,3778,3777,3776,3775,3774,3773,3772,3771,3770,3768,3767,3766,3765,3764,3763,3762,3761,3760,3759,3758,3756,
		3755,3754,3753,3752,3751,3750,3749,3747,3746,3745,3744,3743,3742,3741,3739,3738,3737,3736,3735,3733,3732,3731,3730,3729,3727,3726,3725,3724,3723,3721,3720,3719,
		3718,3716,3715,3714,3713,3711,3710,3709,3707,3706,3705,3704,3702,3701,3700,3698,3697,3696,3694,3693,3692,3691,3689,3688,3687,3685,3684,3682,3681,3680,3678,3677,
		3676,3674,3673,3672,3670,3669,3667,3666,3665,3663,3662,3660,3659,3657,3656,3655,3653,3652,3650,3649,3647,3646,3644,3643,3642,3640,3639,3637,3636,3634,3633,3631,
		3630,3628,3627,3625,3624,3622,3621,3619,3618,3616,3615,3613,3611,3610,3608,3607,3605,3604,3602,3601,3599,3597,3596,3594,3593,3591,3589,3588,3586,3585,3583,3581,
		3580,3578,3577,3575,3573,3572,3570,3568,3567,3565,3563,3562,3560,3558,3557,3555,3553,3552,3550,3548,3547,3545,3543,3542,3540,3538,3536,3535,3533,3531,3530,3528,
		3526,3524,3523,3521,3519,3517,3516,3514,3512,3510,3509,3507,3505,3503,3501,3500,3498,3496,3494,3492,3491,3489,3487,3485,3483,3482,3480,3478,3476,3474,3472,3471,
		3469,3467,3465,3463,3461,3459,3458,3456,3454,3452,3450,3448,3446,3444,3442,3441,3439,3437,3435,3433,3431,3429,3427,3425,3423,3421,3419,3418,3416,3414,3412,3410,
		3408,3406,3404,3402,3400,3398,3396,3394,3392,3390,3388,3386,3384,3382,3380,3378,3376,3374,3372,3370,3368,3366,3364,3362,3360,3358,3356,3354,3352,3350,3348,3346,
		3344,3341,3339,3337,3335,3333,3331,3329,3327,3325,3323,3321,3319,3316,3314,3312,3310,3308,3306,3304,3302,3300,3297,3295,3293,3291,3289,3287,3285,3282,3280,3278,
		3276,3274,3272,3269,3267,3265,3263,3261,3259,3256,3254,3252,3250,3248,3245,3243,3241,3239,3237,3234,3232,3230,3228,3226,3223,3221,3219,3217,3214,3212,3210,3208,
		3205,3203,3201,3199,3196,3194,3192,3190,3187,3185,3183,3180,3178,3176,3174,3171,3169,3167,3164,3162,3160,3157,3155,3153,3150,3148,3146,3144,3141,3139,3137,3134,
		3132,3129,3127,3125,3122,3120,3118,3115,3113,3111,3108,3106,3104,3101,3099,3096,3094,3092,3089,3087,3084,3082,3080,3077,3075,3072,3070,3068,3065,3063,3060,3058,
		3056,3053,3051,3048,3046,3043,3041,3039,3036,3034,3031,3029,3026,3024,3021,3019,3016,3014,3012,3009,3007,3004,3002,2999,2997,2994,2992,2989,2987,2984,2982,2979,
		2977,2974,2972,2969,2967,2964,2962,2959,2957,2954,2952,2949,2947,2944,2942,2939,2937,2934,2931,2929,2926,2924,2921,2919,2916,2914,2911,2908,2906,2903,2901,2898,
		2896,2893,2891,2888,2885,2883,2880,2878,2875,2872,2870,2867,2865,2862,2859,2857,2854,2852,2849,2846,2844,2841,2839,2836,2833,2831,2828,2826,2823,2820,2818,2815,
		2812,2810,2807,2804,2802,2799,2797,2794,2791,2789,2786,2783,2781,2778,2775,2773,2770,2767,2765,2762,2759,2757,2754,2751,2749,2746,2743,2741,2738,2735,2732,2730,
		2727,2724,2722,2719,2716,2714,2711,2708,2706,2703,2700,2697,2695,2692,2689,2687,2684,2681,2678,2676,2673,2670,2667,2665,2662,2659,2657,2654,2651,2648,2646,2643,
		2640,2637,2635,2632,2629,2626,2624,2621,2618,2615,2613,2610,2607,2604,2602,2599,2596,2593,2590,2588,2585,2582,2579,2577,2574,2571,2568,2565,2563,2560,2557,2554,
		2552,2549,2546,2543,2540,2538,2535,2532,2529,2526,2524,2521,2518,2515,2512,2510,2507,2504,2501,2498,2496,2493,2490,2487,2484,2481,2479,2476,2473,2470,2467,2464,
		2462,2459,2456,2453,2450,2448,2445,2442,2439,2436,2433,2430,2428,2425,2422,2419,2416,2413,2411,2408,2405,2402,2399,2396,2394,2391,2388,2385,2382,2379,2376,2374,
		2371,2368,2365,2362,2359,2356,2354,2351,2348,2345,2342,2339,2336,2333,2331,2328,2325,2322,2319,2316,2313,2310,2308,2305,2302,2299,2296,2293,2290,2287,2285,2282,
		2279,2276,2273,2270,2267,2264,2261,2259,2256,2253,2250,2247,2244,2241,2238,2235,2233,2230,2227,2224,2221,2218,2215,2212,2209,2207,2204,2201,2198,2195,2192,2189,
		2186,2183,2180,2178,2175,2172,2169,2166,2163,2160,2157,2154,2151,2148,2146,2143,2140,2137,2134,2131,2128,2125,2122,2119,2117,2114,2111,2108,2105,2102,2099,2096,
		2093,2090,2087,2084,2082,2079,2076,2073,2070,2067,2064,2061,2058,2055,2052,2050,2047,2044,2041,2038,2035,2032,2029,2026,2023,2020,2017,2015,2012,2009,2006,2003,
		2000,1997,1994,1991,1988,1985,1983,1980,1977,1974,1971,1968,1965,1962,1959,1956,1953,1950,1948,1945,1942,1939,1936,1933,1930,1927,1924,1921,1918,1916,1913,1910,
		1907,1904,1901,1898,1895,1892,1889,1886,1883,1881,1878,1875,1872,1869,1866,1863,1860,1857,1854,1852,1849,1846,1843,1840,1837,1834,1831,1828,1825,1822,1820,1817,
		1814,1811,1808,1805,1802,1799,1796,1793,1791,1788,1785,1782,1779,1776,1773,1770,1767,1765,1762,1759,1756,1753,1750,1747,1744,1741,1739,1736,1733,1730,1727,1724,
		1721,1718,1715,1713,1710,1707,1704,1701,1698,1695,1692,1690,1687,1684,1681,1678,1675,1672,1669,1667,1664,1661,1658,1655,1652,1649,1646,1644,1641,1638,1635,1632,
		1629,1626,1624,1621,1618,1615,1612,1609,1606,1604,1601,1598,1595,1592,1589,1587,1584,1581,1578,1575,1572,1570,1567,1564,1561,1558,1555,1552,1550,1547,1544,1541,
		1538,1536,1533,1530,1527,1524,1521,1519,1516,1513,1510,1507,1504,1502,1499,1496,1493,1490,1488,1485,1482,1479,1476,1474,1471,1468,1465,1462,1460,1457,1454,1451,
		1448,1446,1443,1440,1437,1435,1432,1429,1426,1423,1421,1418,1415,1412,1410,1407,1404,1401,1398,1396,1393,1390,1387,1385,1382,1379,1376,1374,1371,1368,1365,1363,
		1360,1357,1354,1352,1349,1346,1343,1341,1338,1335,1333,1330,1327,1324,1322,1319,1316,1313,1311,1308,1305,1303,1300,1297,1294,1292,1289,1286,1284,1281,1278,1276,
		1273,1270,1268,1265,1262,1259,1257,1254,1251,1249,1246,1243,1241,1238,1235,1233,1230,1227,1225,1222,1219,1217,1214,1211,1209,1206,1203,1201,1198,1196,1193,1190,
		1188,1185,1182,1180,1177,1174,1172,1169,1167,1164,1161,1159,1156,1154,1151,1148,1146,1143,1141,1138,1135,1133,1130,1128,1125,1122,1120,1117,1115,1112,1109,1107,
		1104,1102,1099,1097,1094,1092,1089,1086,1084,1081,1079,1076,1074,1071,1069,1066,1063,1061,1058,1056,1053,1051,1048,1046,1043,1041,1038,1036,1033,1031,1028,1026,
		1023,1021,1018,1016,1013,1011,1008,1006,1003,1001,998,996,993,991,988,986,984,981,979,976,974,971,969,966,964,961,959,957,954,952,949,947,
		944,942,940,937,935,932,930,928,925,923,920,918,916,913,911,908,906,904,901,899,896,894,892,889,887,885,882,880,878,875,873,871,
		868,866,863,861,859,856,854,852,850,847,845,843,840,838,836,833,831,829,826,824,822,820,817,815,813,810,808,806,804,801,799,797,
		795,792,790,788,786,783,781,779,777,774,772,770,768,766,763,761,759,757,755,752,750,748,746,744,741,739,737,735,733,731,728,726,
		724,722,720,718,715,713,711,709,707,705,703,700,698,696,694,692,690,688,686,684,681,679,677,675,673,671,669,667,665,663,661,659,
		656,654,652,650,648,646,644,642,640,638,636,634,632,630,628,626,624,622,620,618,616,614,612,610,608,606,604,602,600,598,596,594,
		592,590,588,586,584,582,581,579,577,575,573,571,569,567,565,563,561,559,558,556,554,552,550,548,546,544,542,541,539,537,535,533,
		531,529,528,526,524,522,520,518,517,515,513,511,509,508,506,504,502,500,499,497,495,493,491,490,488,486,484,483,481,479,477,476,
		474,472,470,469,467,465,464,462,460,458,457,455,453,452,450,448,447,445,443,442,440,438,437,435,433,432,430,428,427,425,423,422,
		420,419,417,415,414,412,411,409,407,406,404,403,401,399,398,396,395,393,392,390,389,387,385,384,382,381,379,378,376,375,373,372,
		370,369,367,366,364,363,361,360,358,357,356,354,353,351,350,348,347,345,344,343,341,340,338,337,335,334,333,331,330,328,327,326,
		324,323,322,320,319,318,316,315,313,312,311,309,308,307,306,304,303,302,300,299,298,296,295,294,293,291,290,289,287,286,285,284,
		282,281,280,279,277,276,275,274,273,271,270,269,268,267,265,264,263,262,261,259,258,257,256,255,254,253,251,250,249,248,247,246,
		245,244,242,241,240,239,238,237,236,235,234,233,232,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,
		211,210,209,208,207,206,205,204,203,202,201,201,200,199,198,197,196,195,194,193,192,191,190,190,189,188,187,186,185,184,184,183,
		182,181,180,179,178,178,177,176,175,174,174,173,172,171,170,170,169,168,167,167,166,165,164,163,163,162,161,161,160,159,158,158,
		157,156,156,155,154,153,153,152,151,151,150,149,149,148,147,147,146,146,145,144,144,143,142,142,141,141,140,139,139,138,138,137,
		137,136,135,135,134,134,133,133,132,132,131,131,130,129,129,128,128,127,127,126,126,126,125,125,124,124,123,123,122,122,121,121,
		121,120,120,119,119,118,118,118,117,117,117,116,116,115,115,115,114,114,114,113,113,113,112,112,112,111,111,111,110,110,110,109,
		109,109,109,108,108,108,108,107,107,107,107,106,106,106,106,105,105,105,105,105,104,104,104,104,104,103,103,103,103,103,103,102,
		102,102,102,102,102,102,102,101,101,101,101,101,101,101,101,101,101,101,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
		100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,101,101,101,101,101,101,101,101,101,101,101,102,102,102,102,102,102,
		102,102,103,103,103,103,103,103,104,104,104,104,104,105,105,105,105,105,106,106,106,106,107,107,107,107,108,108,108,108,109,109,
		109,109,110,110,110,111,111,111,112,112,112,113,113,113,114,114,114,115,115,115,116,116,117,117,117,118,118,118,119,119,120,120,
		121,121,121,122,122,123,123,124,124,125,125,126,126,126,127,127,128,128,129,129,130,131,131,132,132,133,133,134,134,135,135,136,
		137,137,138,138,139,139,140,141,141,142,142,143,144,144,145,146,146,147,147,148,149,149,150,151,151,152,153,153,154,155,156,156,
		157,158,158,159,160,161,161,162,163,163,164,165,166,167,167,168,169,170,170,171,172,173,174,174,175,176,177,178,178,179,180,181,
		182,183,184,184,185,186,187,188,189,190,190,191,192,193,194,195,196,197,198,199,200,201,201,202,203,204,205,206,207,208,209,210,
		211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,232,233,234,235,236,237,238,239,240,241,242,244,
		245,246,247,248,249,250,251,253,254,255,256,257,258,259,261,262,263,264,265,267,268,269,270,271,273,274,275,276,277,279,280,281,
		282,284,285,286,287,289,290,291,293,294,295,296,298,299,300,302,303,304,306,307,308,309,311,312,313,315,316,318,319,320,322,323,
		324,326,327,328,330,331,333,334,335,337,338,340,341,343,344,345,347,348,350,351,353,354,356,357,358,360,361,363,364,366,367,369,
		370,372,373,375,376,378,379,381,382,384,385,387,389,390,392,393,395,396,398,399,401,403,404,406,407,409,411,412,414,415,417,419,
		420,422,423,425,427,428,430,432,433,435,437,438,440,442,443,445,447,448,450,452,453,455,457,458,460,462,464,465,467,469,470,472,
		474,476,477,479,481,483,484,486,488,490,491,493,495,497,499,500,502,504,506,508,509,511,513,515,517,518,520,522,524,526,528,529,
		531,533,535,537,539,541,542,544,546,548,550,552,554,556,558,559,561,563,565,567,569,571,573,575,577,579,581,582,584,586,588,590,
		592,594,596,598,600,602,604,606,608,610,612,614,616,618,620,622,624,626,628,630,632,634,636,638,640,642,644,646,648,650,652,654,
		656,659,661,663,665,667,669,671,673,675,677,679,681,684,686,688,690,692,694,696,698,700,703,705,707,709,711,713,715,718,720,722,
		724,726,728,731,733,735,737,739,741,744,746,748,750,752,755,757,759,761,763,766,768,770,772,774,777,779,781,783,786,788,790,792,
		795,797,799,801,804,806,808,810,813,815,817,820,822,824,826,829,831,833,836,838,840,843,845,847,850,852,854,856,859,861,863,866,
		868,871,873,875,878,880,882,885,887,889,892,894,896,899,901,904,906,908,911,913,916,918,920,923,925,928,930,932,935,937,940,942,
		944,947,949,952,954,957,959,961,964,966,969,971,974,976,979,981,984,986,988,991,993,996,998,1001,1003,1006,1008,1011,1013,1016,1018,1021,
		1023,1026,1028,1031,1033,1036,1038,1041,1043,1046,1048,1051,1053,1056,1058,1061,1063,1066,1069,1071,1074,1076,1079,1081,1084,1086,1089,1092,1094,1097,1099,1102,
		1104,1107,1109,1112,1115,1117,1120,1122,1125,1128,1130,1133,1135,1138,1141,1143,1146,1148,1151,1154,1156,1159,1161,1164,1167,1169,1172,1174,1177,1180,1182,1185,
		1188,1190,1193,1196,1198,1201,1203,1206,1209,1211,1214,1217,1219,1222,1225,1227,1230,1233,1235,1238,1241,1243,1246,1249,1251,1254,1257,1259,1262,1265,1268,1270,
		1273,1276,1278,1281,1284,1286,1289,1292,1294,1297,1300,1303,1305,1308,1311,1313,1316,1319,1322,1324,1327,1330,1333,1335,1338,1341,1343,1346,1349,1352,1354,1357,
		1360,1363,1365,1368,1371,1374,1376,1379,1382,1385,1387,1390,1393,1396,1398,1401,1404,1407,1410,1412,1415,1418,1421,1423,1426,1429,1432,1435,1437,1440,1443,1446,
		1448,1451,1454,1457,1460,1462,1465,1468,1471,1474,1476,1479,1482,1485,1488,1490,1493,1496,1499,1502,1504,1507,1510,1513,1516,1519,1521,1524,1527,1530,1533,1536,
		1538,1541,1544,1547,1550,1552,1555,1558,1561,1564,1567,1570,1572,1575,1578,1581,1584,1587,1589,1592,1595,1598,1601,1604,1606,1609,1612,1615,1618,1621,1624,1626,
		1629,1632,1635,1638,1641,1644,1646,1649,1652,1655,1658,1661,1664,1667,1669,1672,1675,1678,1681,1684,1687,1690,1692,1695,1698,1701,1704,1707,1710,1713,1715,1718,
		1721,1724,1727,1730,1733,1736,1739,1741,1744,1747,1750,1753,1756,1759,1762,1765,1767,1770,1773,1776,1779,1782,1785,1788,1791,1793,1796,1799,1802,1805,1808,1811,
		1814,1817,1820,1822,1825,1828,1831,1834,1837,1840,1843,1846,1849,1852,1854,1857,1860,1863,1866,1869,1872,1875,1878,1881,1883,1886,1889,1892,1895,1898,1901,1904,
		1907,1910,1913,1916,1918,1921,1924,1927,1930,1933,1936,1939,1942,1945,1948,1950,1953,1956,1959,1962,1965,1968,1971,1974,1977,1980,1983,1985,1988,1991,1994,1997
};
const char wavheader[44]={0x52,0x49,0x46,0x46,
                          0xFF,0xFF,0xFF,0xFF,
						  0x57,0x41,0x56,0x45,
						  0x66,0x6d,0x74,0x20,
						  0x10,0x00,0x00,0x00,
						  0x01,0x00,
						  0x02,0x00,
						  0x80,0x3E,0x00,0x00,
						  0x0,0xFA,0x00,0x00,
						  0x04,0x00,
						  0x10,0x00,
						  0x64,0x61,0x74,0x61,
						  0xFF,0xFF,0xFF,0xFF};
const char toneheader[44]={0x52,0x49,0x46,0x46,
                           0xFF,0xFF,0xFF,0xFF,
						   0x57,0x41,0x56,0x45,
						   0x66,0x6d,0x74,0x20,
						   0x10,0x00,0x00,0x00,
						   0x01,0x00,
						   0x02,0x00,
						   0x44,0xAC,0x00,0x00,
						   0x10,0xB1,0x02,0x00,
						   0x04,0x00,
						   0x10,0x00,
						   0x64,0x61,0x74,0x61,
						   0xFF,0xFF,0xFF,0xFF};

void __not_in_flash_func(iconvert)(uint16_t *ibuff, int16_t *sbuff, int count){
	int i;
	for(i=0;i<(count);i+=2){
		ibuff[i]=(uint16_t)((((int)sbuff[i]*mapping[vol_left]/2000+32768))>>4);
		ibuff[i+1]=(uint16_t)((((int)sbuff[i+1]*mapping[vol_right]/2000+32768))>>4);
	}
}
void MIPS64 __not_in_flash_func(i2sconvert)(int16_t *fbuff, int16_t *sbuff, int count){
	int i;
	for(i=0;i<(count);i+=2){
		sbuff[i]=(int16_t)((int)(fbuff[i])*mapping[vol_left]/2000);
		sbuff[i+1]=(int32_t)((int)(fbuff[i+1])*mapping[vol_right]/2000);
	}
}

size_t onRead(void  *userdata,  char  *pBufferOut,   size_t bytesToRead){
    unsigned int nbr;
	if(filesource[WAV_fnbr]==FATFSFILE){
		FSerror=f_read(FileTable[WAV_fnbr].fptr,pBufferOut, bytesToRead, &nbr);
		if(FSerror)nbr=0;
    	if(!MDD_SDSPI_CardDetectState())ErrorCheck(WAV_fnbr);
	} else {
		nbr=lfs_file_read(&lfs, FileTable[WAV_fnbr].lfsptr, pBufferOut, bytesToRead);
		if(nbr<0)FSerror=nbr;	
		else FSerror=0;
		ErrorCheck(WAV_fnbr);
	}
    return nbr;
}
drwav_bool32 onSeek(void  *userdata,  int offset,  drwav_seek_origin origin){
	if(filesource[WAV_fnbr]==FATFSFILE){
		if(origin==drwav_seek_origin_start) FSerror=f_lseek(FileTable[WAV_fnbr].fptr,offset);
		else FSerror=f_lseek(FileTable[WAV_fnbr].fptr,FileTable[WAV_fnbr].fptr->fptr+offset);
	} else {
		if(origin==drwav_seek_origin_start) FSerror=lfs_file_seek(&lfs, FileTable[WAV_fnbr].lfsptr, offset, LFS_SEEK_SET);
		else FSerror=lfs_file_seek(&lfs, FileTable[WAV_fnbr].lfsptr, offset, LFS_SEEK_CUR);
	}
    return 1;
}
/*drwav_bool32 onTell(void  *userdata,  drwav_int64* pCursor){
	if(filesource[WAV_fnbr]==FATFSFILE){
		*pCursor=(*(FileTable[WAV_fnbr].fptr)).fptr;
	} else {
		*pCursor=lfs_file_tell(&lfs,FileTable[WAV_fnbr].lfsptr);
	}
    return 1;
}*/

void CloseAudio(int all){
#ifdef rp2350
	if(!PSRAMsize)
#endif
	modbuff =  (Option.modbuff ?  (char *)(XIP_BASE + RoundUpK4(TOP_OF_SYSTEM_FLASH)) : NULL);
	int was_playing=CurrentlyPlaying;
	if(!Option.audio_i2s_bclk){
		bcount[1] = bcount[2] = wav_filesize = 0;
		swingbuf = nextbuf = playreadcomplete = 0;
	}
	StopAudio();
	if(CurrentlyPlaying==P_WAVOPEN)CurrentlyPlaying=P_NOTHING;
	ForceFileClose(WAV_fnbr);
	FreeMemorySafe((void **)&sbuff1);
	FreeMemorySafe((void **)&sbuff2);
	FreeMemorySafe((void **)&noisetable);
	//FreeMemorySafe((void **)&usertable);
	usertable=NULL;
	FreeMemorySafe((void **)&mcontext);
	if(all){
		FreeMemorySafe((void **)&alist);
		trackstoplay=0;
		trackplaying=0;
	}
	memset(WAVfilename,0,sizeof(WAVfilename));
	WAVcomplete = true;
	FSerror = 0;
	if(was_playing == P_FLAC || was_playing == P_PAUSE_FLAC )FreeMemorySafe((void **)&myflac);
	if(was_playing == P_WAV || was_playing == P_PAUSE_WAV )FreeMemorySafe((void **)&mywav);
#ifdef rp2350
	if((was_playing == P_MP3 || was_playing == P_PAUSE_MP3 ) && (Option.AUDIO_L || Option.audio_i2s_bclk || Option.AUDIO_MOSI_PIN)){
		drmp3_uninit(mymp3);
		FreeMemorySafe((void **)&mymp3);
	}
	if(PSRAMsize && was_playing == P_MOD)FreeMemorySafe((void **)&modbuff);
#endif
    int i;
    for(i=0;i<MAXSOUNDS;i++){
    	sound_PhaseM_left[i]=0;
    	sound_PhaseM_right[i]=0;
    	sound_PhaseAC_left[i]=0;
    	sound_PhaseAC_right[i]=0;
    	sound_mode_left[i]=(uint16_t *)nulltable;
    	sound_mode_right[i]=(uint16_t *)nulltable;
    }
	if(XDCS!=-1){
		VS1053reset(XRST);
		XDCS = XCS = DREQ = XRST = -1;
		midienabled=0;
		streamsize=0;
		streamwritepointer=NULL;
		streamreadpointer=NULL;
		streambuffer=NULL;
	}
    return;
}
void setrate(int rate){
	static int lastrate=0;
	if(rate==lastrate)return;
	lastrate=rate;
	AUDIO_WRAP=(Option.CPU_Speed*1000)/rate  - 1 ;
	pwm_set_wrap(AUDIO_SLICE, AUDIO_WRAP);
	if(Option.AUDIO_L){
		pwm_set_both_levels(AUDIO_SLICE,(int)(((AUDIO_WRAP>>1)*4000)/4096),(int)(((AUDIO_WRAP>>1)*4000)/4096));
	}
	pwm_clear_irq(AUDIO_SLICE);
	if(Option.audio_i2s_bclk){
		float clockdiv=(Option.CPU_Speed*1000.0f)/(float)(rate*128);
		pio_sm_set_clkdiv(pioi2s,i2ssm,clockdiv);
	}
}
void playvs1053(int mode){
	XCS=PinDef[Option.AUDIO_CS_PIN].GPno;
	XDCS=PinDef[Option.AUDIO_DCS_PIN].GPno;
	DREQ=PinDef[Option.AUDIO_DREQ_PIN].GPno;
	XRST=PinDef[Option.AUDIO_RESET_PIN].GPno;
	VS1053(XCS,XDCS,DREQ,XRST);
	switchToMp3Mode();
	loadDefaultVs1053Patches(); 
	setVolumes(vol_left,vol_right);
	//playing a file
	setrate(6000); //32KHz should be fast enough
	if(mode==P_MOD){
		memcpy((char *)sbuff1,wavheader,sizeof(wavheader));
		bcount[1]=44;
		wav_filesize=bcount[1];
	} else {
		sbuff1 = GetMemory(WAV_BUFFER_SIZE);
		sbuff2 = GetMemory(WAV_BUFFER_SIZE);
		bcount[1]=onRead(NULL,sbuff1,WAV_BUFFER_SIZE);
		wav_filesize=bcount[1];
	}
	CurrentlyPlaying = mode;
	swingbuf=1;
	nextbuf=2;
	ppos=0;
	playreadcomplete=0;
	pwm_set_irq0_enabled(AUDIO_SLICE, true);
	pwm_set_enabled(AUDIO_SLICE, true); 
	uint64_t t=time_us_64();
	uSec(25);
	while(1){ //read all the headers without stalling
		checkWAVinput();
		uSec(25);
		if(time_us_64()-t>500000)break;
	}
}
void playimmediatevs1053(int play){
	if(CurrentlyPlaying==P_WAVOPEN)return;
	XCS=PinDef[Option.AUDIO_CS_PIN].GPno;
	XDCS=PinDef[Option.AUDIO_DCS_PIN].GPno;
	DREQ=PinDef[Option.AUDIO_DREQ_PIN].GPno;
	XRST=PinDef[Option.AUDIO_RESET_PIN].GPno;
	VS1053(XCS,XDCS,DREQ,XRST);
	switchToMp3Mode();
	loadDefaultVs1053Patches(); 
	setVolumes(vol_left,vol_right);
	//playing a file
	setrate(PWM_FREQ); //16KHz should be fast enough
	CurrentlyPlaying = play;
	playChunk((uint8_t *)toneheader,sizeof(toneheader));
}
void wavcallback(char *p){
	int actualrate;
    if(strchr((char *)p, '.') == NULL) strcat((char *)p, ".wav");
    if(CurrentlyPlaying == P_WAV){
    	CloseAudio(0);
    }
    WAV_fnbr = FindFreeFileNbr();
    if(!BasicFileOpen(p, WAV_fnbr, FA_READ)) return;
	strcpy(WAVfilename,p);
	if(Option.AUDIO_MISO_PIN){
		playvs1053(P_WAV);
		return;
	}
	drwav_allocation_callbacks allocationCallbacks;
    allocationCallbacks.pUserData = NULL;
    allocationCallbacks.onMalloc  = my_malloc;
    allocationCallbacks.onRealloc = NULL;
    allocationCallbacks.onFree    = my_free;
	mywav=GetMemory(sizeof(drwav));
    drwav_init(mywav,(drwav_read_proc)onRead, (drwav_seek_proc)onSeek, NULL, &allocationCallbacks);
    if(mywav->sampleRate>44100*((int)(Option.CPU_Speed/126000)))error("Max %KHz sample rate",44100*((int)(Option.CPU_Speed/126000)));
//        PInt(mywav.channels);MMPrintString(" Channels\r\n");
//        PInt(mywav.bitsPerSample);MMPrintString(" Bits per sample\r\n");
//        PInt(mywav.sampleRate);MMPrintString(" Sample rate\r\n");
	if(Option.AUDIO_L){
		audiorepeat=1;
		actualrate=mywav->sampleRate;
		while(actualrate<32000){
			actualrate +=mywav->sampleRate;
			audiorepeat++;
		}
		setrate(actualrate);
	} else {
		setrate(mywav->sampleRate);
	}
    FreeMemorySafe((void **)&sbuff1);
    FreeMemorySafe((void **)&sbuff2);
    sbuff1 = GetMemory(WAV_BUFFER_SIZE);
    sbuff2 = GetMemory(WAV_BUFFER_SIZE);
    ubuff1 = (uint16_t *)sbuff1;
    ubuff2 = (uint16_t *)sbuff2;
	mono=(mywav->channels == 1 ? 1 : 0);
    g_buff1 = (int16_t *)sbuff1;
    g_buff2 = (int16_t *)sbuff2;
	bcount[1]=(volatile unsigned int)drwav_read_pcm_frames_s16(mywav, WAV_BUFFER_SIZE/4, (drwav_int16*)sbuff1) * mywav->channels;
	if(Option.audio_i2s_bclk) i2sconvert((drwav_int16*)sbuff1,(drwav_int16*)sbuff1,bcount[1]);
	else iconvert(ubuff1, (int16_t *)sbuff1, bcount[1]);
    wav_filesize=bcount[1];
    CurrentlyPlaying = P_WAV;
    swingbuf=1;
    nextbuf=2;
    ppos=0;
    playreadcomplete=0;
	pwm_set_irq0_enabled(AUDIO_SLICE, true);
	pwm_set_enabled(AUDIO_SLICE, true); 
}
void mp3callback(char *p, int position){
    if(strchr((char *)p, '.') == NULL) strcat((char *)p, ".mp3");
    if(CurrentlyPlaying == P_MP3){
    	CloseAudio(0);
    }
    WAV_fnbr = FindFreeFileNbr();
	strcpy(WAVfilename,p);
    if(!BasicFileOpen(p, WAV_fnbr, FA_READ)) return;
	if(Option.AUDIO_MISO_PIN){
		positionfile(WAV_fnbr, position);
		playvs1053(P_MP3);
		return;
	}
#ifdef rp2350
	int actualrate;
	drmp3_allocation_callbacks allocationCallbacks;
    allocationCallbacks.pUserData = NULL;
    allocationCallbacks.onMalloc  = my_malloc;
    allocationCallbacks.onRealloc = my_realloc;
    allocationCallbacks.onFree    = my_free;
    if(CurrentlyPlaying == P_MP3){
    	CloseAudio(0);
    }
	mymp3=GetMemory(sizeof(drmp3));
    if(drmp3_init(mymp3, (drmp3_read_proc)onRead, (drmp3_seek_proc)onSeek, NULL, &allocationCallbacks)==DRMP3_FALSE)error("Mp3 init");
    FreeMemorySafe((void *)&sbuff1);
    FreeMemorySafe((void *)&sbuff2);
//	PInt(mymp3->channels);MMPrintString(" Channels\r\n");
//	PInt(mymp3->sampleRate);MMPrintString(" Sample rate\r\n");
    sbuff1 = GetMemory(MP3_BUFFER_SIZE);
    sbuff2 = GetMemory(MP3_BUFFER_SIZE);
    ubuff1 = (uint16_t *)sbuff1;
    ubuff2 = (uint16_t *)sbuff2;
    g_buff1 = (int16_t *)sbuff1;
    g_buff2 = (int16_t *)sbuff2;
	mono=(mymp3->channels == 1 ? 1 : 0);
	if(Option.AUDIO_L){
		audiorepeat=1;
		actualrate=mymp3->sampleRate;
		while(actualrate<PWM_FREQ){
			actualrate +=mymp3->sampleRate;
			audiorepeat++;
		}
		setrate(actualrate);
	} else {
		setrate(mymp3->sampleRate);
	}
    bcount[1]=drmp3_read_pcm_frames_s16(mymp3, MP3_BUFFER_SIZE/4, (drmp3_int16*)sbuff1) * mymp3->channels;
    if(!Option.audio_i2s_bclk)iconvert(ubuff1, (int16_t *)sbuff1, bcount[1]);
	else i2sconvert(g_buff1, (int16_t *)sbuff1, bcount[1]);
    wav_filesize=bcount[1];
    CurrentlyPlaying = P_MP3;
    swingbuf=1;
    nextbuf=2;
    ppos=0;
    playreadcomplete=0;
	pwm_set_irq0_enabled(AUDIO_SLICE, true);
	pwm_set_enabled(AUDIO_SLICE, true); 
//	MMPrintString("Playing ");MMPrintString(p);PRet();
#endif
}
void midicallback(char *p){
    if(strchr((char *)p, '.') == NULL) strcat((char *)p, ".mid");
    if(CurrentlyPlaying == P_MIDI){
    	CloseAudio(0);
    }
    WAV_fnbr = FindFreeFileNbr();
    if(!BasicFileOpen(p, WAV_fnbr, FA_READ)) return;
	strcpy(WAVfilename,p);
	playvs1053(P_MIDI);
}
void flaccallback(char *p){
	int actualrate;
    if(strchr((char *)p, '.') == NULL) strcat((char *)p, ".flac");
    if(CurrentlyPlaying == P_FLAC){
    	CloseAudio(0);
    }
    WAV_fnbr = FindFreeFileNbr();
    if(!BasicFileOpen(p, WAV_fnbr, FA_READ)) return;
	strcpy(WAVfilename,p);
	if(Option.AUDIO_MISO_PIN){
		playvs1053(P_FLAC);
		return;
	}
	drflac_allocation_callbacks allocationCallbacks;
    allocationCallbacks.pUserData = NULL;
    allocationCallbacks.onMalloc  = my_malloc;
    allocationCallbacks.onRealloc = my_realloc;
    allocationCallbacks.onFree    = my_free;
    myflac=drflac_open((drflac_read_proc)onRead, (drflac_seek_proc)onSeek, NULL, &allocationCallbacks);
#ifdef rp2350
    if(myflac->sampleRate>48000*((int)((float)Option.CPU_Speed/126000.0f)))error("Max %KHz sample rate",48000*((int)((float)Option.CPU_Speed/126000.0f)));
#else
    if(myflac->sampleRate>44100*((int)((float)Option.CPU_Speed/126000.0f)))error("Max %KHz sample rate",44100*((int)((float)Option.CPU_Speed/126000.0f)));
#endif
//	PInt(myflac->channels);MMPrintString(" Channels\r\n");
//	PInt(myflac->bitsPerSample);MMPrintString(" Bits per sample\r\n");
//	PInt(myflac->sampleRate);MMPrintString(" Sample rate\r\n");
	mono=(myflac->channels == 1 ? 1 : 0);
	if(Option.AUDIO_L){
		audiorepeat=1;
		actualrate=myflac->sampleRate;
		while(actualrate<PWM_FREQ){
			actualrate +=myflac->sampleRate;
			audiorepeat++;
		}
		setrate(actualrate);
	} else {
		setrate(myflac->sampleRate);
	}
    FreeMemorySafe((void **)&sbuff1);
    FreeMemorySafe((void **)&sbuff2);
    sbuff1 = GetMemory(FLAC_BUFFER_SIZE);
    sbuff2 = GetMemory(FLAC_BUFFER_SIZE);
    ubuff1 = (uint16_t *)sbuff1;
    ubuff2 = (uint16_t *)sbuff2;
    g_buff1 = (int16_t *)sbuff1;
    g_buff2 = (int16_t *)sbuff2;
	if(Option.audio_i2s_bclk){
		bcount[1]=(volatile unsigned int)drflac_read_pcm_frames_s16(myflac, FLAC_BUFFER_SIZE/4, (drwav_int16*)sbuff1) * myflac->channels;
		i2sconvert((drwav_int16*)sbuff1,(drwav_int16*)sbuff1,bcount[1]);
	}
	else
	{
		bcount[1]=(volatile unsigned int)drflac_read_pcm_frames_s16(myflac, FLAC_BUFFER_SIZE/4, (drwav_int16*)sbuff1) * myflac->channels;
		iconvert(ubuff1, (int16_t *)sbuff1, bcount[1]);
	}
    wav_filesize=bcount[1];
    CurrentlyPlaying = P_FLAC;
    swingbuf=1;
    nextbuf=2;
    ppos=0;
    playreadcomplete=0;
	pwm_set_irq0_enabled(AUDIO_SLICE, true);
	pwm_set_enabled(AUDIO_SLICE, true); 

}
void rampvolume(int l, int r, int channel, int target){
	if(optionfastaudio){
		if(l)sound_v_left[channel]=target;
		if(r)sound_v_right[channel]=target;
	} else {
		int ramptime=1000000/PWM_FREQ+2;
		if(l && r){
			if(sound_v_left[channel]>target){
				for(int i=sound_v_left[channel]-1;i>=target;i--){
					sound_v_left[channel]=i;
					sound_v_right[channel]=i;
					uSec(ramptime);
				}
			} else {
				for(int i=sound_v_left[channel]+1;i<=target;i++){
					sound_v_left[channel]=i;
					sound_v_right[channel]=i;
					uSec(ramptime);
				}
			}
		} else if(l){
			if(sound_v_left[channel]>target){
				for(int i=sound_v_left[channel]-1;i>=target;i--){
					sound_v_left[channel]=i;
					uSec(ramptime);
				}
			} else {
				for(int i=sound_v_left[channel]+1;i<=target;i++){
					sound_v_left[channel]=i;
					uSec(ramptime);
				}
			}
		} else if(r){
			if(sound_v_right[channel]>target){
				for(int i=sound_v_right[channel]-1;i>=target;i--){
					sound_v_right[channel]=i;
					uSec(ramptime);
				}
			} else {
				for(int i=sound_v_right[channel]+1;i<=target;i++){
					sound_v_right[channel]=i;
					uSec(ramptime);
				}
			}
		}
	}
}

void setnoise(void){
    uint32_t noise;
    int i;
    if(noisetable)return;
	noisetable=GetMemory(4096*sizeof(uint16_t));
    for(i=0;i<4096;i++){
    	noise=rand() % 3800+100;
        noisetable[i]=(int)noise;
    }
    return;

}
/*  @endcond */
// The MMBasic command:  PLAY
void MIPS16 cmd_play(void) {
    unsigned char *tp;
    if(checkstring(cmdline, (unsigned char *)"STOP")) {
		if(CurrentlyPlaying == P_NOTHING)return;
        CloseAudio(1);
        return;
    }
	if(!(Option.AUDIO_L || Option.AUDIO_CLK_PIN || Option.audio_i2s_bclk))error((char *)"Audio not enabled");
    if((tp=checkstring(cmdline, (unsigned char *)"LOAD SOUND"))) {
		if(Option.AUDIO_MISO_PIN)error("Not available with VS1053 audio");
        if(usertable!=NULL)error("Already loaded");
//        unsigned int nbr;
        uint16_t *dd;
		int64_t *aint;
		skipspace(tp);
		int size=parseintegerarray(tp,&aint,1,1,NULL,false);
       	dd = (uint16_t *)aint;
        if(size!=1024) error("Array size");
		usertable=dd;
        return;
    }
    if(checkstring(cmdline, (unsigned char *)"NEXT")) {
		if(CurrentlyPlaying == P_FLAC){
			if(trackplaying==trackstoplay){
				if(!CurrentLinePtr)MMPrintString("Last track is playing\r\n");
				return;
			}
			trackplaying++;
			flaccallback(alist[trackplaying].fn);
		} else if(CurrentlyPlaying == P_WAV){
			if(trackplaying==trackstoplay){
				if(!CurrentLinePtr)MMPrintString("Last track is playing\r\n");
				return;
			}
			trackplaying++;
			wavcallback(alist[trackplaying].fn);
		} else if(CurrentlyPlaying == P_MP3){
			if(trackplaying==trackstoplay){
				if(!CurrentLinePtr)MMPrintString("Last track is playing\r\n");
				return;
			}
			trackplaying++;
			mp3callback(alist[trackplaying].fn,0);
		} else if(CurrentlyPlaying == P_MIDI){
			if(trackplaying==trackstoplay){
				if(!CurrentLinePtr)MMPrintString("Last track is playing\r\n");
				return;
			}
			trackplaying++;
			midicallback(alist[trackplaying].fn);
		} else error("Nothing to play");

    	return;
    }
    if(checkstring(cmdline, (unsigned char *)"PREVIOUS")) {
		if(CurrentlyPlaying == P_FLAC){
			if(trackplaying==0){
				if(!CurrentLinePtr)MMPrintString("First track is playing\r\n");
				return;
			}
			trackplaying--;
			flaccallback(alist[trackplaying].fn);
		} else if(CurrentlyPlaying == P_WAV){
			if(trackplaying==0){
				if(!CurrentLinePtr)MMPrintString("First track is playing\r\n");
				return;
			}
			trackplaying--;
			wavcallback(alist[trackplaying].fn);
		} else if(CurrentlyPlaying == P_MP3){
			if(trackplaying==0){
				if(!CurrentLinePtr)MMPrintString("First track is playing\r\n");
				return;
			}
			trackplaying--;
			mp3callback(alist[trackplaying].fn,0);
		} else if(CurrentlyPlaying == P_MIDI){
			if(trackplaying==0){
				if(!CurrentLinePtr)MMPrintString("First track is playing\r\n");
				return;
			}
			trackplaying--;
			midicallback(alist[trackplaying].fn);
		} else error("Nothing to play");

    	return;
    }
    if(checkstring(cmdline, (unsigned char *)"PAUSE")) {
		if(CurrentlyPlaying<P_STOP)return; //already paused
        if(CurrentlyPlaying == P_TONE) CurrentlyPlaying = P_PAUSE_TONE;
        else if(CurrentlyPlaying == P_SOUND) CurrentlyPlaying = P_PAUSE_SOUND;
        else if(CurrentlyPlaying == P_WAV)  CurrentlyPlaying = P_PAUSE_WAV;
        else if(CurrentlyPlaying == P_FLAC)  CurrentlyPlaying = P_PAUSE_FLAC;
        else if(CurrentlyPlaying == P_MP3)  CurrentlyPlaying = P_PAUSE_MP3;
        else if(CurrentlyPlaying == P_MOD)  CurrentlyPlaying = P_PAUSE_MOD;
        else
            error("Nothing playing");
        return;
    }
    if(checkstring(cmdline, (unsigned char *)"RESUME")) {
        if(CurrentlyPlaying == P_PAUSE_TONE) CurrentlyPlaying = P_TONE;
        else if(CurrentlyPlaying == P_PAUSE_SOUND) CurrentlyPlaying = P_SOUND;
        else if(CurrentlyPlaying == P_PAUSE_WAV) CurrentlyPlaying = P_WAV;
        else if(CurrentlyPlaying == P_PAUSE_FLAC) CurrentlyPlaying = P_FLAC;
        else if(CurrentlyPlaying == P_PAUSE_MP3)  CurrentlyPlaying = P_MP3;
        else if(CurrentlyPlaying == P_PAUSE_MOD)  CurrentlyPlaying = P_MOD;
        else
            error("Nothing to resume");  
        return;
    }
    if(checkstring(cmdline, (unsigned char *)"CLOSE")) {
        CloseAudio(1);
        return;
    }
    if((tp = checkstring(cmdline, (unsigned char *)"VOLUME"))) {
        getargs(&tp, 3,(unsigned char *)",");
        if(argc < 1) error("Argument count");
        if(*argv[0]) vol_left = getint(argv[0], 0, 100);
        if(argc == 3) vol_right = getint(argv[2], 0, 100);
		if(CurrentlyPlaying==P_TONE && vol_left!=vol_right && mono)mono=0;
		if(Option.AUDIO_MISO_PIN && CurrentlyPlaying!=P_NOTHING){
			pwm_set_irq0_enabled(AUDIO_SLICE, false);
			setVolumes(vol_left, vol_right);
			pwm_set_irq0_enabled(AUDIO_SLICE, true);
			pwm_set_enabled(AUDIO_SLICE, true); 
		}
        return;
    }
    if((tp = checkstring(cmdline, (unsigned char *)"TONE"))) {//
		SoundPlay=1000;                                   // this MUST be the first executable line in the function
        float f_left, f_right;
        float hw, duration;
        uint64_t PlayDuration = 0xffffffffffffffff;                     // default is to play forever
//        uint64_t  x;
        {// get the command line arguments
			getargs(&tp, 7,(unsigned char *)","); 
			if(!(argc == 3 || argc == 5 || argc == 7)) error("Argument count");
//			if(Option.AUDIO_MISO_PIN)error("Not available with VS1053 audio");
			mono=0;
			if(!(CurrentlyPlaying == P_NOTHING || CurrentlyPlaying == P_TONE || CurrentlyPlaying == P_PAUSE_TONE || CurrentlyPlaying == P_STOP || CurrentlyPlaying == P_WAVOPEN)) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);
			f_left = getnumber(argv[0]);                         // get the arguments
			f_right = getnumber(argv[2]);
			if(f_left==f_right && vol_left==vol_right)mono=1;
			if(f_left<0.0 || f_left>22050.0)error("Valid is 0Hz to 20KHz");
			if(f_right<0.0 || f_right>22050.0)error("Valid is 0Hz to 20KHz");
			if(argc > 4) {
				duration = ((float)getint(argv[4], 0, INT_MAX)/1000.0); //tone duration in seconds
				PlayDuration=(uint64_t)duration;
			} else duration=1;
			if(argc == 7) {
				if(!CurrentLinePtr)error("No program running");
				WAVInterrupt = (char *)GetIntAddress(argv[6]);					// get the interrupt location
				WAVcomplete=false;
				InterruptUsed = true;
			}
			if(duration == 0) return;
			if(PlayDuration != 0xffffffffffffffff && f_left >=10.0){
				hw=((float)PWM_FREQ/(float)f_left); //number of interrupts per cycle
				duration = duration * (float)PWM_FREQ; // number of interrupts for the requested waveform
	// This should now be an exact multiple of the number per waveform
				PlayDuration=(((uint64_t)(duration/hw))*hw);
			}
			pwm_set_irq0_enabled(AUDIO_SLICE, false);
			PhaseM_left =  f_left  / (float)PWM_FREQ * 4096.0;
			PhaseM_right = f_right  / (float)PWM_FREQ * 4096.0;
			WAV_fnbr=0;

			SoundPlay = PlayDuration;
			if (!(CurrentlyPlaying == P_PAUSE_TONE || CurrentlyPlaying == P_TONE )){
				setrate(PWM_FREQ);
				PhaseAC_right=0.0;
				PhaseAC_left=0.0;
				if(Option.AUDIO_MISO_PIN)playimmediatevs1053(P_TONE);
			}
			CurrentlyPlaying = P_TONE;
			pwm_set_irq0_enabled(AUDIO_SLICE, true);
			pwm_set_enabled(AUDIO_SLICE, true); 
			return;
		}
    }
    if((tp = checkstring(cmdline, (unsigned char *)"SOUND"))) {//PLAY SOUND channel, type, position, frequency, volume
        float f_in, PhaseM;
        int channel, left=0, right=0, lset=0, rset=0, local_sound_v_left=0,local_sound_v_right=0;
		char *p;
        uint16_t *lastleft=NULL, *lastright=NULL, *local_sound_mode_left=(uint16_t *)nulltable, *local_sound_mode_right=(uint16_t *)nulltable;
        // get the command line arguments
        getargs(&tp, 9,(unsigned char *)",");                                       // this MUST be the first executable line in the function
        if(!(argc == 9 || argc == 7 || argc == 5)) error("Argument count");
        if(checkstring(argv[4],(unsigned char *)"O")==NULL && argc == 5) error("Argument count");
		WAV_fnbr=0;
        channel=getint(argv[0],1,MAXSOUNDS)-1;
        lastleft=local_sound_mode_left=(uint16_t *)sound_mode_left[channel];
        lastright=local_sound_mode_right=(uint16_t *)sound_mode_right[channel];
        if(checkstring(argv[2],(unsigned char *)"L")!=NULL){
        	left=1;
        } else if(checkstring(argv[2],(unsigned char *)"R")!=NULL){
        	right=1;
        } else if(checkstring(argv[2],(unsigned char *)"B")!=NULL){
        	right=1;
        	left=1;
       } else {
			p=(char *)getCstring(argv[2]);
			if(strcasecmp(p,"B")==0){
				right=1;
				left=1;
			} else if(strcasecmp(p,"M")==0){
				right=1;
				left=1;
			} else if (strcasecmp(p,"L")==0){
				left=1;
			} else if (strcasecmp(p,"R")==0){
				right=1;
			} else error("Position must be L, R, or B");
		}
        if(!(CurrentlyPlaying == P_NOTHING || CurrentlyPlaying == P_SOUND || CurrentlyPlaying == P_PAUSE_SOUND || CurrentlyPlaying == P_STOP || CurrentlyPlaying == P_WAVOPEN)) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);
        if(checkstring(argv[4],(unsigned char *)"O")!=NULL && left){lset=1;local_sound_mode_left=(uint16_t *)nulltable;}
        if(checkstring(argv[4],(unsigned char *)"O")!=NULL && right){rset=1;local_sound_mode_right=(uint16_t *)nulltable;}
        if(checkstring(argv[4],(unsigned char *)"Q")!=NULL && left){lset=1;local_sound_mode_left=(uint16_t *)squaretable;}
        if(checkstring(argv[4],(unsigned char *)"Q")!=NULL && right){rset=1;local_sound_mode_right=(uint16_t *)squaretable;}
        if(checkstring(argv[4],(unsigned char *)"T")!=NULL && left){lset=1;local_sound_mode_left=(uint16_t *)triangletable;}
        if(checkstring(argv[4],(unsigned char *)"T")!=NULL && right){rset=1;local_sound_mode_right=(uint16_t *)triangletable;}
        if(checkstring(argv[4],(unsigned char *)"W")!=NULL && left){lset=1;local_sound_mode_left=(uint16_t *)sawtable;}
        if(checkstring(argv[4],(unsigned char *)"W")!=NULL && right){rset=1;local_sound_mode_right=(uint16_t *)sawtable;}
        if(checkstring(argv[4],(unsigned char *)"S")!=NULL && left){lset=1;local_sound_mode_left=(uint16_t *)SineTable;}
        if(checkstring(argv[4],(unsigned char *)"S")!=NULL && right){rset=1;local_sound_mode_right=(uint16_t *)SineTable;}
        if(checkstring(argv[4],(unsigned char *)"P")!=NULL && left){lset=1;setnoise();local_sound_mode_left=(uint16_t *)noisetable;}
        if(checkstring(argv[4],(unsigned char *)"P")!=NULL && right){rset=1;setnoise();local_sound_mode_right=(uint16_t *)noisetable;}
        if(checkstring(argv[4],(unsigned char *)"N")!=NULL && left){lset=1;local_sound_mode_left=(uint16_t *)whitenoise;}
        if(checkstring(argv[4],(unsigned char *)"N")!=NULL && right){rset=1;local_sound_mode_right=(uint16_t *)whitenoise;}
        if(checkstring(argv[4],(unsigned char *)"U")!=NULL && left){lset=1;local_sound_mode_left=(uint16_t *)usertable;}
        if(checkstring(argv[4],(unsigned char *)"U")!=NULL && right){rset=1;local_sound_mode_right=(uint16_t *)usertable;}
		if(left && lset==0){
			p=(char *)getCstring(argv[4]);
			if(strcasecmp(p,"O")==0)local_sound_mode_left=(uint16_t *)nulltable;
			if(strcasecmp(p,"Q")==0)local_sound_mode_left=(uint16_t *)squaretable;
			if(strcasecmp(p,"T")==0)local_sound_mode_left=(uint16_t *)triangletable;
			if(strcasecmp(p,"W")==0)local_sound_mode_left=(uint16_t *)sawtable;
			if(strcasecmp(p,"S")==0)local_sound_mode_left=(uint16_t *)SineTable;
			if(strcasecmp(p,"P")==0){setnoise();local_sound_mode_left=(uint16_t *)noisetable;}
			if(strcasecmp(p,"N")==0)local_sound_mode_left=(uint16_t *)whitenoise;
			if(strcasecmp(p,"U")==0)local_sound_mode_left=(uint16_t *)usertable;
			if(local_sound_mode_left==NULL)error("Invalid type");
			else lset=1;
		}
		if(right && rset==0){
			p=(char *)getCstring(argv[4]);
			if(strcasecmp(p,"O")==0)local_sound_mode_right=(uint16_t *)nulltable;
			if(strcasecmp(p,"Q")==0)local_sound_mode_right=(uint16_t *)squaretable;
			if(strcasecmp(p,"T")==0)local_sound_mode_right=(uint16_t *)triangletable;
			if(strcasecmp(p,"W")==0)local_sound_mode_right=(uint16_t *)sawtable;
			if(strcasecmp(p,"S")==0)local_sound_mode_right=(uint16_t *)SineTable;
			if(strcasecmp(p,"P")==0){setnoise();local_sound_mode_right=(uint16_t *)noisetable;;}
			if(strcasecmp(p,"N")==0)local_sound_mode_right=(uint16_t *)whitenoise;
			if(strcasecmp(p,"U")==0)local_sound_mode_right=(uint16_t *)usertable;
			if(local_sound_mode_right==NULL)error("Invalid type");
			else rset=1;
		}
		if((local_sound_mode_left==usertable || local_sound_mode_right==usertable) && usertable==NULL) error("Not loaded");
        f_in=10.0;
        if(argc>=7)f_in = getnumber(argv[6]);
        // get the arguments
        if(f_in<1.0 || f_in>20000.0)error("Valid is 1Hz to 20KHz");
        if(left){
        	if(!(sound_mode_left[channel]==whitenoise )){
        		PhaseM =  f_in  / (float)PWM_FREQ * 4096.0;
        	} else {
        		PhaseM =  f_in;
        	}
        	if(lastleft!=local_sound_mode_left){
				if(!Option.AUDIO_MISO_PIN)rampvolume(1,0,channel,0);
				sound_PhaseAC_left[channel] = 0.0;
			}
        	sound_PhaseM_left[channel] = PhaseM;
            if(argc==9)local_sound_v_left=getint(argv[8],0,100/MAXSOUNDS);
            else local_sound_v_left=25;
			local_sound_v_left=local_sound_v_left*41/(100/MAXSOUNDS);
        }
        if(right){
        	if(!(sound_mode_right[channel]==whitenoise )){
        		PhaseM =  f_in  / (float)PWM_FREQ * 4096.0;
        	} else {
        		PhaseM =  f_in;
        	}
        	if(lastright!=local_sound_mode_right){
				if(!Option.AUDIO_MISO_PIN)rampvolume(0,1,channel,0);
				sound_PhaseAC_right[channel] = 0.0;
			}
        	sound_PhaseM_right[channel] = PhaseM;
            if(argc==9)local_sound_v_right=getint(argv[8],0,100/MAXSOUNDS);
            else local_sound_v_right=25;
			local_sound_v_right=local_sound_v_right*41/(100/MAXSOUNDS);
        }
		if(left && right && local_sound_v_left==local_sound_v_right && sound_v_left[channel]==sound_v_right[channel]  && !Option.AUDIO_MISO_PIN)rampvolume(1,1,channel,local_sound_v_left);
		else {
			if(left  && !Option.AUDIO_MISO_PIN)rampvolume(1,0,channel,local_sound_v_left);
			if(right  && !Option.AUDIO_MISO_PIN)rampvolume(0,1,channel,local_sound_v_right);
		}
		if(left)sound_mode_left[channel]=local_sound_mode_left;
		if(right)sound_mode_right[channel]=local_sound_mode_right;
        if(!(CurrentlyPlaying == P_SOUND || CurrentlyPlaying==P_PAUSE_SOUND)){
			setrate(PWM_FREQ);
			if(Option.AUDIO_MISO_PIN)playimmediatevs1053(P_SOUND);
    		pwm_set_irq0_enabled(AUDIO_SLICE, true);
			pwm_set_enabled(AUDIO_SLICE, true); 
		}
        CurrentlyPlaying = P_SOUND;
        return;
    }
    if((tp = checkstring(cmdline, (unsigned char *)"WAV"))) {
        char *p;
        int i __attribute((unused))=0;
        getargs(&tp, 3,(unsigned char *)",");                                  // this MUST be the first executable line in the function
        if(!(argc == 1 || argc == 3)) error("Argument count");
		if(CurrentlyPlaying==P_WAVOPEN)CloseAudio(1);
        if(CurrentlyPlaying != P_NOTHING) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);

        if(!InitSDCard()) return;
        p = (char *)getFstring(argv[0]);                                    // get the file name
		char q[FF_MAX_LFN]={0};
		getfullfilename(p,q);
        WAVInterrupt = NULL;
        WAVcomplete = 0;
        if(argc == 3) {
			if(!CurrentLinePtr)error("No program running");
            WAVInterrupt = (char *)GetIntAddress(argv[2]);					// get the interrupt location
            InterruptUsed = true;
        }
		if(FatFSFileSystem){
			FRESULT fr;
			FILINFO fno;
			int i;
			if(ExistsDir(q,q,&i)){
				alist=GetMemory(sizeof(a_flist)*MAXALBUM);
				trackstoplay=0;
				trackplaying=0;
				DIR djd;
				djd.pat="*.wav";
				if(!CurrentLinePtr)MMPrintString("Directory found - commencing player\r\n");
				FSerror = f_opendir(&djd, q);
				for(;;){
					fr=f_readdir(&djd, &fno);
					if (fr != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */
					// Get a directory item
					if (pattern_matching(djd.pat, fno.fname, 0, 0)){
					// Get a directory item
						strcpy(alist[trackstoplay].fn,"B:");
						strcat(alist[trackstoplay].fn,q);
						strcat(alist[trackstoplay].fn,"/");
						strcat(alist[trackstoplay].fn,fno.fname);
						str_replace(alist[trackstoplay].fn, "//", "/",3);
						str_replace(alist[trackstoplay].fn, "/./", "/",3);
						if(!CurrentLinePtr){
							MMPrintString(fno.fname);
							PRet();
						}
						trackstoplay++;
						if(trackstoplay==MAXALBUM)break;
					}
				}
				trackstoplay--;
				f_closedir(&djd);
				wavcallback(alist[trackplaying].fn);
				return;
    	    }
		}
        // open the file
        trackstoplay=0;
        trackplaying=0;
		memset(q,0,sizeof(q));
		getfullfilename(p,q);
		memmove(&q[2],q,strlen(q));
		q[1]=':';
		q[0]=FatFSFileSystem ? 'B' : 'A';
        wavcallback(q);
        return;
    }
	if((tp = checkstring(cmdline, (unsigned char *)"FLAC"))) {
        char *p;
        int i __attribute((unused))=0;
        getargs(&tp, 3,(unsigned char *)",");                                  // this MUST be the first executable line in the function
        if(!(argc == 1 || argc == 3)) error("Argument count");
		if(CurrentlyPlaying==P_WAVOPEN)CloseAudio(1);
        if(CurrentlyPlaying != P_NOTHING) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);

        if(!InitSDCard()) return;
        p = (char *)getFstring(argv[0]);                                    // get the file name
		char q[FF_MAX_LFN]={0};
		getfullfilename(p,q);
        WAVInterrupt = NULL;
        WAVcomplete = 0;
        if(argc == 3) {
			if(!CurrentLinePtr)error("No program running");
            WAVInterrupt = (char *)GetIntAddress(argv[2]);					// get the interrupt location
            InterruptUsed = true;
        }
		if(FatFSFileSystem){
			FRESULT fr;
			FILINFO fno;
			int i;
			if(ExistsDir(q,q,&i)){
				alist=GetMemory(sizeof(a_flist)*MAXALBUM);
				trackstoplay=0;
				trackplaying=0;
				DIR djd;
				djd.pat="*.flac";
				if(!CurrentLinePtr)MMPrintString("Directory found - commencing player\r\n");
				FSerror = f_opendir(&djd, q);
				for(;;){
					fr=f_readdir(&djd, &fno);
					if (fr != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */
					// Get a directory item
					if (pattern_matching(djd.pat, fno.fname, 0, 0)){
					// Get a directory item
						strcpy(alist[trackstoplay].fn,"B:");
						strcat(alist[trackstoplay].fn,q);
						strcat(alist[trackstoplay].fn,"/");
						strcat(alist[trackstoplay].fn,fno.fname);
						str_replace(alist[trackstoplay].fn, "//", "/",3);
						str_replace(alist[trackstoplay].fn, "/./", "/",3);
						if(!CurrentLinePtr){
							MMPrintString(fno.fname);
							PRet();
						}
						trackstoplay++;
						if(trackstoplay==MAXALBUM)break;
					}
				}
				trackstoplay--;
				f_closedir(&djd);
				flaccallback(alist[trackplaying].fn);
				return;
    	    }
		}
        // open the file
        trackstoplay=0;
        trackplaying=0;
		memset(q,0,sizeof(q));
		getfullfilename(p,q);
		memmove(&q[2],q,strlen(q));
		q[1]=':';
		q[0]=FatFSFileSystem ? 'B' : 'A';
        flaccallback(q);
        return;
	}
	if((tp = checkstring(cmdline, (unsigned char *)"NOTE"))) {
		if(!Option.AUDIO_MISO_PIN)error("Only available with VS1053 audio");
		if(!midienabled)error("Midi output not enabled");
		unsigned char *xp;
		if((xp = checkstring(tp, (unsigned char *)"ON"))) {
			getargs(&xp,5,(unsigned char *)",");
			if(!(argc==5))error("Syntax");
			uint8_t channel=getint(argv[0],0,15);
			uint8_t note=getint(argv[2],0,127);
			uint8_t velocity=getint(argv[4],0,127);
			noteOn(channel,note,velocity);
		} else if((xp = checkstring(tp, (unsigned char *)"OFF"))) {
			getargs(&xp,5,(unsigned char *)",");
			if(!(argc==5 || argc==3))error("Syntax");
			uint8_t channel=getint(argv[0],0,15);
			uint8_t note=getint(argv[2],0,127);
			uint8_t velocity=0;
			if(argc==5)velocity=getint(argv[4],0,127);
			noteOff(channel,note,velocity);
		} else error("Syntax");
		return;
	}
    if((tp = checkstring(cmdline, (unsigned char *)"STREAM"))) {
		getargs(&tp,5,(unsigned char *)",");
        if(!(argc == 5 )) error("Syntax");
		if(!Option.AUDIO_MISO_PIN)error("Only available with VS1053 audio");
		if(CurrentlyPlaying==P_WAVOPEN)CloseAudio(1);
        if(CurrentlyPlaying != P_NOTHING) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);
		WAVInterrupt = NULL;
		WAVcomplete = 0;
		if(XDCS!=-1)error("VS1053 already open");
		void *ptr1 = NULL;
		int64_t *aint;
		streamsize=parseintegerarray(argv[0], &aint, 1, 1, NULL, true) * 8;
		streambuffer=(char *)aint;
		ptr1 = findvar(argv[2], V_FIND | V_EMPTY_OK | V_NOFIND_ERR);
		if(g_vartbl[g_VarIndex].type & T_INT) {
				if(g_vartbl[g_VarIndex].dims[0] != 0) error("Argument 2 must be an integer");
				streamreadpointer = (int *)ptr1;
		} else error("Argument 2 must be an integer");
		ptr1 = findvar(argv[4], V_FIND | V_EMPTY_OK | V_NOFIND_ERR);
		if(g_vartbl[g_VarIndex].type & T_INT) {
				if(g_vartbl[g_VarIndex].dims[0] != 0) error("Argument 3 must be an integer");
				streamwritepointer = (int *)ptr1;
		} else error("Argument 3 must be an integer");
		XCS=PinDef[Option.AUDIO_CS_PIN].GPno;
		XDCS=PinDef[Option.AUDIO_DCS_PIN].GPno;
		DREQ=PinDef[Option.AUDIO_DREQ_PIN].GPno;
		XRST=PinDef[Option.AUDIO_RESET_PIN].GPno;
		VS1053(XCS,XDCS,DREQ,XRST);
		switchToMp3Mode();
		loadDefaultVs1053Patches(); 
		setVolumes(vol_left,vol_right);
		MMPrintString("Stream output enabled\r\n");	
		playreadcomplete=0;
		CurrentlyPlaying=P_STREAM;
		setrate(16000); //16KHz should be fast enough
		pwm_set_irq0_enabled(AUDIO_SLICE, true);
		pwm_set_enabled(AUDIO_SLICE, true); 
		return;
	}
	if((tp = checkstring(cmdline, (unsigned char *)"MIDI"))) {
		unsigned char *xp;
		if((xp = checkstring(tp, (unsigned char *)"CMD"))) {
			getargs(&xp,5,(unsigned char *)",");
			if(!midienabled)error("Midi output not enabled");
			if(!(argc==5 || argc==3))error("Syntax");
			uint8_t cmd=getint(argv[0],128,255);
			uint8_t data1=getint(argv[2],0,127);
			uint8_t data2=0;
			if(argc==5)data2=getint(argv[4],0,127);
			talkMIDI(cmd, data1, data2);
			return;
		}
		if((xp = checkstring(tp, (unsigned char *)"TEST"))) {
			getargs(&xp,1,(unsigned char *)",");
			if(!midienabled)error("Midi output not enabled");
			miditest(getint(argv[0],1,3));	
			return;
		}
		if(!Option.AUDIO_MISO_PIN)error("Only available with VS1053 audio");
		if(CurrentlyPlaying==P_WAVOPEN)CloseAudio(1);
        if(CurrentlyPlaying != P_NOTHING) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);
		WAVInterrupt = NULL;
		WAVcomplete = 0;
		XCS=PinDef[Option.AUDIO_CS_PIN].GPno;
		XDCS=PinDef[Option.AUDIO_DCS_PIN].GPno;
		DREQ=PinDef[Option.AUDIO_DREQ_PIN].GPno;
		XRST=PinDef[Option.AUDIO_RESET_PIN].GPno;
		VS1053(XCS,XDCS,DREQ,XRST);
		setVolumes(vol_left,vol_right);
		midienabled=1;
		miditest(0);
		if(!CurrentLinePtr)MMPrintString("Real Time MIDI mode enabled\r\n");
		return;
	}
	if((tp = checkstring(cmdline, (unsigned char *)"MIDIFILE"))) {
        char *p;
        int i __attribute((unused))=0;
        getargs(&tp, 3,(unsigned char *)",");                                  // this MUST be the first executable line in the function
        if(!(argc == 1 || argc == 3)) error("Argument count");
		if(!Option.AUDIO_MISO_PIN)error("Only available with VS1053 audio");
		if(CurrentlyPlaying==P_WAVOPEN)CloseAudio(1);
        if(CurrentlyPlaying != P_NOTHING) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);

        if(!InitSDCard()) return;
        p = (char *)getFstring(argv[0]);                                    // get the file name
		char q[FF_MAX_LFN]={0};
		getfullfilename(p,q);
        WAVInterrupt = NULL;

        WAVcomplete = 0;
        if(argc == 3) {
			if(!CurrentLinePtr)error("No program running");
            WAVInterrupt = (char *)GetIntAddress(argv[2]);					// get the interrupt location
            InterruptUsed = true;
        }
		if(FatFSFileSystem){
			FRESULT fr;
			FILINFO fno;
			int i;
			if(ExistsDir(q,q,&i)){
				alist=GetMemory(sizeof(a_flist)*MAXALBUM);
				trackstoplay=0;
				trackplaying=0;
				DIR djd;
				djd.pat="*.mid";
				if(!CurrentLinePtr)MMPrintString("Directory found - commencing player\r\n");
				FSerror = f_opendir(&djd, q);
				for(;;){
					fr=f_readdir(&djd, &fno);
					if (fr != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */
					// Get a directory item
					if (pattern_matching(djd.pat, fno.fname, 0, 0)){
					// Get a directory item
						strcpy(alist[trackstoplay].fn,"B:");
						strcat(alist[trackstoplay].fn,q);
						strcat(alist[trackstoplay].fn,"/");
						strcat(alist[trackstoplay].fn,fno.fname);
						str_replace(alist[trackstoplay].fn, "//", "/",3);
						str_replace(alist[trackstoplay].fn, "/./", "/",3);
						if(!CurrentLinePtr){
							MMPrintString(fno.fname);
							PRet();
						}
						trackstoplay++;
						if(trackstoplay==MAXALBUM)break;
					}
				}
				trackstoplay--;
				f_closedir(&djd);
				midicallback(alist[trackplaying].fn);
				return;
    	    }
		}
        // open the file
        trackstoplay=0;
        trackplaying=0;
		memset(q,0,sizeof(q));
		getfullfilename(p,q);
		memmove(&q[2],q,strlen(q));
		q[1]=':';
		q[0]=FatFSFileSystem ? 'B' : 'A';
        midicallback(q);
        return;
	}
	if((tp = checkstring(cmdline, (unsigned char *)"HALT"))) {
        if(CurrentlyPlaying != P_MP3) error("Not playing an MP3");
    	int fnbr = FindFreeFileNbr();
		char *buff=GetTempMemory(STRINGSIZE);
		char *p=&WAVfilename[strlen(WAVfilename)];
		while(*p-- != '/'){}
		p+=2;
		strcpy(buff,"A:/");
		strcat(buff,p);
		str_replace(buff,".mp3",".mem",1);
		str_replace(buff,".MP3",".mem",1);
		str_replace(buff,".Mp3",".mem",1);
		str_replace(buff,".mP3",".mem",1);
    	if(!BasicFileOpen(buff, fnbr,  FA_WRITE | FA_CREATE_ALWAYS)) return;
		int i;
		if(filesource[WAV_fnbr]==FLASHFILE)i = lfs_file_tell(&lfs,FileTable[fnbr].lfsptr) + 1;
        else i = (*(FileTable[WAV_fnbr].fptr)).fptr + 1;
		i-=418;
		if(i<0)i=0;
		IntToStr(buff,i,10);
		FilePutStr(strlen(buff),buff,fnbr);
		FilePutChar(',',fnbr);
		FilePutStr(strlen(WAVfilename),WAVfilename,fnbr);
		FileClose(fnbr);
		CloseAudio(1);
		return;
	}
	if((tp = checkstring(cmdline, (unsigned char *)"CONTINUE"))) {
		if(!Option.AUDIO_MISO_PIN)error("Only available with VS1053 audio");
    	int fnbr = FindFreeFileNbr();
		char *p=(char *)getFstring(tp);
		char *buff=GetTempMemory(STRINGSIZE);
		if(strchr(p,'/') || strchr(p,':') || strchr(p,'\\') || strchr(p,'.'))error("Track name");
		strcpy(buff, "A:/");
		strcat(buff,p);
		strcat(buff,".mem");
		if(!ExistsFile(buff))error("Track name");
    	if(!BasicFileOpen(buff, fnbr,  FA_READ)) return;
		memset(buff,0,STRINGSIZE);
		lfs_file_read(&lfs, FileTable[fnbr].lfsptr, buff, 255);
		FileClose(fnbr);
		p=strchr(buff,',');
		p++;
		int num=atoi(buff);
        WAVInterrupt = NULL;
        WAVcomplete = 0;
        trackstoplay=0;
        trackplaying=0;
		mp3callback(p,num);
		return;
	}
	if((tp = checkstring(cmdline, (unsigned char *)"MP3"))) {
        char *p;
        int i __attribute((unused))=0;
        getargs(&tp, 3,(unsigned char *)",");                                  // this MUST be the first executable line in the function
        if(!(argc == 1 || argc == 3)) error("Argument count");
#ifndef rp2350
		if(!Option.AUDIO_MISO_PIN)error("Only available with VS1053 audio");
#else
        if(Option.CPU_Speed<200000 && !Option.AUDIO_MISO_PIN)error("CPUSPEED >=200000 for MP3 playback");
#endif
		if(CurrentlyPlaying==P_WAVOPEN)CloseAudio(1);
        if(CurrentlyPlaying != P_NOTHING) error("Sound output in use for $",PlayingStr[CurrentlyPlaying]);

        if(!InitSDCard()) return;
        p = (char *)getFstring(argv[0]);                                    // get the file name
		char q[FF_MAX_LFN]={0};
		getfullfilename(p,q);
        WAVInterrupt = NULL;
        WAVcomplete = 0;
        if(argc == 3) {
			if(!CurrentLinePtr)error("No program running");
            WAVInterrupt = (char *)GetIntAddress(argv[2]);					// get the interrupt location
            InterruptUsed = true;
        }
		if(FatFSFileSystem){
			FRESULT fr;
			FILINFO fno;
			int i;
			if(ExistsDir(q,q,&i)){
				alist=GetMemory(sizeof(a_flist)*MAXALBUM);
				trackstoplay=0;
				trackplaying=0;
				DIR djd;
				djd.pat="*.mp3";
				if(!CurrentLinePtr)MMPrintString("Directory found - commencing player\r\n");
				FSerror = f_opendir(&djd, q);
				for(;;){
					fr=f_readdir(&djd, &fno);
					if (fr != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */
					// Get a directory item
					if (pattern_matching(djd.pat, fno.fname, 0, 0)){
					// Get a directory item
						strcpy(alist[trackstoplay].fn,"B:");
						strcat(alist[trackstoplay].fn,q);
						strcat(alist[trackstoplay].fn,"/");
						strcat(alist[trackstoplay].fn,fno.fname);
						str_replace(alist[trackstoplay].fn, "//", "/",3);
						str_replace(alist[trackstoplay].fn, "/./", "/",3);
						if(!CurrentLinePtr){
							MMPrintString(fno.fname);
							PRet();
						}
						trackstoplay++;
						if(trackstoplay==MAXALBUM)break;
					}
				}
				trackstoplay--;
				f_closedir(&djd);
				mp3callback(alist[trackplaying].fn,0);
				return;
    	    }
		}
        // open the file
        trackstoplay=0;
        trackplaying=0;
		memset(q,0,sizeof(q));
		getfullfilename(p,q);
		memmove(&q[2],q,strlen(q));
		q[1]=':';
		q[0]=FatFSFileSystem ? 'B' : 'A';
        mp3callback(q,0);
        return;
	}
    if((tp = checkstring(cmdline, (unsigned char *)"MODFILE"))) {
        getargs(&tp, 3,(unsigned char *)",");                                  // this MUST be the first executable line in the function
        char *p;
        int i __attribute((unused))=0,fsize;
        modfilesamplerate=22050;
		if(CurrentlyPlaying==P_WAVOPEN)CloseAudio(1);
        if(CurrentlyPlaying != P_NOTHING) error("Sound output in use");
#ifdef rp2350
		if(!(modbuff || PSRAMsize))error("Mod playback not enabled");
#else
		if(!(modbuff))error("Mod playback not enabled");
#endif
        if(!InitSDCard()) return;
        sbuff1 = GetMemory(MOD_BUFFER_SIZE);
        sbuff2 = GetMemory(MOD_BUFFER_SIZE);
        ubuff1 = (uint16_t *)sbuff1;
        ubuff2 = (uint16_t *)sbuff2;
        g_buff1 = (int16_t *)sbuff1;
        g_buff2 = (int16_t *)sbuff2;
        p = (char *)getFstring(argv[0]);                                    // get the file name
        WAVInterrupt = NULL;
        WAVcomplete = 0;
        // open the file
        if(strchr((char *)p, '.') == NULL) strcat((char *)p, ".MOD");
		char q[FF_MAX_LFN]={0};
		getfullfilename(p,q);
		memmove(&q[2],q,strlen(q));
		q[1]=':';
		q[0]=FatFSFileSystem ? 'B' : 'A';
		strcpy(WAVfilename,q);
        WAV_fnbr = FindFreeFileNbr();
        if(!BasicFileOpen(p, WAV_fnbr, FA_READ)) return;
		if(argc==3){
			if(!CurrentLinePtr)error("No program running");
            WAVInterrupt = (char *)GetIntAddress(argv[2]);					// get the interrupt location
            InterruptUsed = true;
			noloop=1;
        } else noloop=0;
        i=0;
		if(filesource[WAV_fnbr]!=FLASHFILE)  fsize = f_size(FileTable[WAV_fnbr].fptr);
		else fsize = lfs_file_size(&lfs,FileTable[WAV_fnbr].lfsptr);
		int alreadythere=1;
#ifdef rp2350
		if(!PSRAMsize){
#endif
			if(RoundUpK4(fsize)>1024*Option.modbuffsize)error("File too large for modbuffer");
			char *check=modbuff;
			while(!FileEOF(WAV_fnbr)) { 
				if(*check++ != FileGetChar(WAV_fnbr)){
					alreadythere=0;
					break;
				}
			}
#ifdef rp2350
		} else {
			modbuff=GetMemory(RoundUpK4(fsize));
			positionfile(WAV_fnbr,0);
			char *r=modbuff;
			while(!FileEOF(WAV_fnbr)) { 
				*r++=FileGetChar(WAV_fnbr);
			}
		}
#endif
		if(!alreadythere){
			unsigned char *r = GetTempMemory(256);
			positionfile(WAV_fnbr,0);
			uint32_t j = RoundUpK4(TOP_OF_SYSTEM_FLASH);
			disable_interrupts_pico();
			flash_range_erase(j, RoundUpK4(fsize));
			enable_interrupts_pico();
			while(!FileEOF(WAV_fnbr)) { 
				memset(r,0,256) ;
				for(i=0;i<256;i++) {
					if(FileEOF(WAV_fnbr))break;
					r[i] = FileGetChar(WAV_fnbr);
				}  
				disable_interrupts_pico();
				flash_range_program(j, (uint8_t *)r, 256);
				enable_interrupts_pico();
				routinechecks();
				j+=256;
			}
			FileClose(WAV_fnbr);
		}
        FileClose(WAV_fnbr);
		mcontext=GetMemory(sizeof(modcontext));
        hxcmod_init( mcontext );
        hxcmod_setcfg(mcontext, modfilesamplerate,1,1 );
		hxcmod_load( mcontext, (void*)modbuff, fsize );
		if(!mcontext->mod_loaded)error("Load failed");
		if(!CurrentLinePtr){
			MMPrintString("Playing ");MMPrintString((char *)mcontext->song.title);PRet();
		}
		if(Option.AUDIO_MISO_PIN){
			playvs1053(P_MOD);
			return;
		} else {
	        hxcmod_fillbuffer( mcontext, (msample*)sbuff1, MOD_BUFFER_SIZE/8, NULL, noloop );
		}
        wav_filesize=MOD_BUFFER_SIZE/4;
        bcount[1]=MOD_BUFFER_SIZE/4;
        bcount[2]=0;
		if(Option.audio_i2s_bclk)i2sconvert(g_buff1, (int16_t *)sbuff1, bcount[1]);
		else iconvert((uint16_t *)ubuff1, (int16_t *)sbuff1, bcount[1]);
        nchannels=2;
        CurrentlyPlaying = P_MOD;
        swingbuf=1;
        nextbuf=2;
        ppos=0;
        playreadcomplete=0;
        setrate(44100);
		audiorepeat=2;
    	pwm_set_irq0_enabled(AUDIO_SLICE, true);
		pwm_set_enabled(AUDIO_SLICE, true); 
		Timer1=500;
		while(Timer1){
			checkWAVinput();
		#ifdef PICOMITEWEB
			ProcessWeb(1);
		#endif
		}
        return;
    }
    if((tp = checkstring(cmdline, (unsigned char *)"MODSAMPLE"))) {
        unsigned short sampnum, seffectnum;
        unsigned char volume;
        unsigned int samprate, period;
        getargs(&tp, 5,(unsigned char *)",");                                  // this MUST be the first executable line in the function
        if(!(argc == 5 || argc == 3)) error("Argument count");

        if(!(CurrentlyPlaying == P_MOD)) error("Samples play over MOD file");

        sampnum = getint(argv[0],1,32) - 1;

        seffectnum = getint(argv[2],1,NUMMAXSEFFECTS) - 1;

        volume=63;
        if(argc >= 5 && *argv[4]) {
        	volume = getint(argv[4],0,64) - 1;
        	if (volume <0 ) volume = 0;
        }
    	samprate = 16000;

        period = 3579545 / samprate;

        hxcmod_playsoundeffect( mcontext, sampnum, seffectnum, volume, period );
        return;
    }
    error("Unknown command");
}
/* 
 * @cond
 * The following section will be excluded from the documentation.
 */

/******************************************************************************************
Timer interrupt.
Used to send data to the DAC
*******************************************************************************************/

/******************************************************************************************
Stop playing the music or toneb:

*******************************************************************************************/
void StopAudio(void) {

	if(CurrentlyPlaying != P_NOTHING ) {
		int ramptime=1000000/PWM_FREQ-1;
		pwm_set_irq0_enabled(AUDIO_SLICE, false);
		uSec(100); //
		if(!(Option.audio_i2s_bclk))
		{
			uint32_t rr,r=right;
			uint32_t ll,l=left;
			uint32_t m=2000;
			l=m-l;
			r=m-r;
			for(int i=100;i>=0;i--){
				ll=(uint32_t)((int)m-(int)l*i/100);
				rr=(uint32_t)((int)m-(int)r*i/100);
				AudioOutput(ll,rr);
				uSec(ramptime);
			}
			CurrentlyPlaying = P_STOP;
			uSec(ramptime*2);
			setrate(PWM_FREQ);
		}
        ppos=0;
        if(Option.AUDIO_MISO_PIN && (CurrentlyPlaying == P_TONE || CurrentlyPlaying==P_SOUND))CurrentlyPlaying = P_WAVOPEN;
		else CurrentlyPlaying = P_NOTHING;
    }
	SoundPlay = 0;
}
/******************************************************************************************
 * Maintain the WAV sample buffer
*******************************************************************************************/
void checkWAVinput(void){
    audio_checks();
	if(playreadcomplete==1)return;
    if(swingbuf != nextbuf){ //IR has moved to next buffer
		if(Option.AUDIO_MISO_PIN){
			if(CurrentlyPlaying == P_FLAC || CurrentlyPlaying == P_WAV || (CurrentlyPlaying == P_MP3 && Option.AUDIO_MISO_PIN) ||CurrentlyPlaying == P_MIDI){
				if(swingbuf==2){
					bcount[1]=(volatile unsigned int)onRead(NULL,sbuff1,WAV_BUFFER_SIZE);
					wav_filesize = bcount[1];
				} else {
					bcount[2]=(volatile unsigned int)onRead(NULL,sbuff2,WAV_BUFFER_SIZE);
					wav_filesize = bcount[2];
				}
				nextbuf=swingbuf;
				diskchecktimer=DISKCHECKRATE;
			} else if(CurrentlyPlaying == P_MOD){
				if(swingbuf==2){
					if(hxcmod_fillbuffer( mcontext, (msample*)sbuff1, WAV_BUFFER_SIZE/4,NULL, noloop ))playreadcomplete = 1;
					wav_filesize=WAV_BUFFER_SIZE;
					bcount[1]=WAV_BUFFER_SIZE;
				} else {
					if(hxcmod_fillbuffer( mcontext, (msample*)sbuff2, WAV_BUFFER_SIZE/4,NULL, noloop ))playreadcomplete = 1;
					wav_filesize=WAV_BUFFER_SIZE;
					bcount[2]=WAV_BUFFER_SIZE;
				}
				nextbuf=swingbuf;
			}
		} else {
			if(CurrentlyPlaying == P_FLAC){
				if(swingbuf==2){
					bcount[1]=(volatile unsigned int)drflac_read_pcm_frames_s16(myflac, FLAC_BUFFER_SIZE/4, (drwav_int16*)sbuff1) * myflac->channels;
					if(Option.audio_i2s_bclk) i2sconvert((drwav_int16*)sbuff1,(drwav_int16*)sbuff1,bcount[1]);
					else iconvert(ubuff1, (int16_t *)sbuff1, bcount[1]);
					wav_filesize = bcount[1];
				} else {
					bcount[2]=(volatile unsigned int)drflac_read_pcm_frames_s16(myflac, FLAC_BUFFER_SIZE/4, (drwav_int16*)sbuff2) * myflac->channels;
					if(Option.audio_i2s_bclk) i2sconvert((drwav_int16*)sbuff2,(drwav_int16*)sbuff2,bcount[2]);
					else iconvert(ubuff2, (int16_t *)sbuff2, bcount[2]);
					wav_filesize = bcount[2];
				}
				nextbuf=swingbuf;
#ifdef rp2350
			} else if(CurrentlyPlaying == P_MP3){
				if(swingbuf==2){
					bcount[1]=drmp3_read_pcm_frames_s16(mymp3, MP3_BUFFER_SIZE/4, (int16_t *)sbuff1) * mymp3->channels;
					if(!Option.audio_i2s_bclk)iconvert(ubuff1, (int16_t *)sbuff1, bcount[1]);
					else i2sconvert(g_buff1, (int16_t *)sbuff1, bcount[1]);
					wav_filesize = bcount[1];
				} else {
					bcount[2]=drmp3_read_pcm_frames_s16(mymp3, MP3_BUFFER_SIZE/4, (int16_t *)sbuff2) * mymp3->channels;
					if(!Option.audio_i2s_bclk)iconvert(ubuff2, (int16_t *)sbuff2, bcount[2]);
					else i2sconvert(g_buff2, (int16_t *)sbuff2, bcount[2]);
					wav_filesize = bcount[2];
				}
				nextbuf=swingbuf;
#endif
			} else if(CurrentlyPlaying == P_MOD){
				if(swingbuf==2){
					if(hxcmod_fillbuffer( mcontext, (msample*)sbuff1, MOD_BUFFER_SIZE/4,NULL, noloop ))playreadcomplete = 1;
					wav_filesize=MOD_BUFFER_SIZE/2;
					bcount[1]=MOD_BUFFER_SIZE/2;
					if(Option.audio_i2s_bclk)i2sconvert(g_buff1, (int16_t *)sbuff1, bcount[1]);
					else iconvert((uint16_t *)ubuff1, (int16_t *)sbuff1, bcount[1]);
				} else {
					if(hxcmod_fillbuffer( mcontext, (msample*)sbuff2, MOD_BUFFER_SIZE/4,NULL, noloop ))playreadcomplete = 1;
					wav_filesize=MOD_BUFFER_SIZE/2;
					bcount[2]=MOD_BUFFER_SIZE/2;
					if(Option.audio_i2s_bclk)i2sconvert(g_buff2, (int16_t *)sbuff2, bcount[2]);
					else iconvert((uint16_t *)ubuff2, (int16_t *)sbuff2, bcount[2]);
				}
				nextbuf=swingbuf;
			} else if(CurrentlyPlaying == P_WAV){
				if(swingbuf==2){
					bcount[1]=(volatile unsigned int)drwav_read_pcm_frames_s16(mywav, WAV_BUFFER_SIZE/4, (drwav_int16*)sbuff1) * mywav->channels;
					if(Option.audio_i2s_bclk) i2sconvert(g_buff1,(drwav_int16*)sbuff1,bcount[1]);
					else iconvert(ubuff1, (int16_t *)sbuff1, bcount[1]);
					wav_filesize = bcount[1];
				} else {
					bcount[2]=(volatile unsigned int)drwav_read_pcm_frames_s16(mywav, WAV_BUFFER_SIZE/4, (drwav_int16*)sbuff2) * mywav->channels;
					if(Option.audio_i2s_bclk) i2sconvert(g_buff2,(drwav_int16*)sbuff2,bcount[2]);
					else iconvert(ubuff2, (int16_t *)sbuff2, bcount[2]);
					wav_filesize = bcount[2];
				}
				nextbuf=swingbuf;
				diskchecktimer=DISKCHECKRATE;
			} 
		}
	}
    if(wav_filesize<=0 && (CurrentlyPlaying == P_WAV || (CurrentlyPlaying == P_FLAC)|| (CurrentlyPlaying == P_MP3) || (CurrentlyPlaying == P_MIDI))){
    	if(trackplaying==trackstoplay) {
    		playreadcomplete=1;
    	} else {
			if(CurrentlyPlaying == P_WAV){
    			trackplaying++;
    			wavcallback(alist[trackplaying].fn);
    		} else if(CurrentlyPlaying == P_FLAC){
    			trackplaying++;
    			flaccallback(alist[trackplaying].fn);
    		} else if(CurrentlyPlaying == P_MP3){
    			trackplaying++;
    			mp3callback(alist[trackplaying].fn,0);
    		} else if(CurrentlyPlaying == P_MIDI){
				if(Option.AUDIO_MISO_PIN && VSbuffer>32)return;
    			trackplaying++;
    			midicallback(alist[trackplaying].fn);
    		}
		}
    }
}
void audio_checks(void){
    if(playreadcomplete == 1) {
    	if(!(bcount[1] || bcount[2]) ){
			if(Option.AUDIO_MISO_PIN && VSbuffer>32)return;
            if(CurrentlyPlaying == P_FLAC)drflac_close(myflac);
			if(CurrentlyPlaying == P_MOD)FreeMemory((void *)mcontext);
            if(CurrentlyPlaying == P_WAV)FreeMemorySafe((void **)&mywav);
#ifdef rp2350
            if(CurrentlyPlaying == P_MP3 && Option.AUDIO_MISO_PIN==0){
				drmp3_uninit(mymp3);
				FreeMemorySafe((void **)&mymp3);
			}
#endif
            FreeMemorySafe((void **)&sbuff1);
            FreeMemorySafe((void **)&sbuff2);
            FreeMemorySafe((void **)&alist);
            if(Option.AUDIO_MISO_PIN){
    			pwm_set_irq0_enabled(AUDIO_SLICE, false);
				CurrentlyPlaying = P_NOTHING;
			} else StopAudio();
            FileClose(WAV_fnbr);
            WAVcomplete = true;
//            playreadcomplete = 0;
         }
    }
}
/*  @endcond */
